mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
3 Commits
v5.1.164
...
experiment
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f21569269c | ||
![]() |
d98e0622c2 | ||
![]() |
a0ffc5fe8d |
28
.github/ISSUE_TEMPLATE/--bug-report.md
vendored
Normal file
28
.github/ISSUE_TEMPLATE/--bug-report.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: "\U0001F41BBug report"
|
||||
about: Create a bug report about GDevelop or the game engine
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Describe the bug
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
Please double check that the bug is not already reported in the issues list.
|
||||
|
||||
## To Reproduce
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
* Please include a link to a game if possible!
|
||||
* If applicable, add screenshots to help explain your problem.
|
||||
|
||||
## Other details
|
||||
* Include any OS/browser version/smartphone that you're using
|
||||
* Which version of GDevelop are you using? The desktop app or the web-app?
|
||||
* Add any other context about the problem here.
|
71
.github/ISSUE_TEMPLATE/--bug-report.yml
vendored
71
.github/ISSUE_TEMPLATE/--bug-report.yml
vendored
@@ -1,71 +0,0 @@
|
||||
name: 🐛Bug report
|
||||
description: Create a bug report about GDevelop or the game engine
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
options:
|
||||
- label: I have searched the [existing issues](https://github.com/4ian/GDevelop/issues)
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: A clear and concise description of what the bug is.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: |
|
||||
* Please include a link to a game if possible!
|
||||
* If applicable, add screenshots to help explain your problem.
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: GDevelop platform
|
||||
description: Which platform of GDevelop are you using?
|
||||
multiple: true
|
||||
options:
|
||||
- Desktop
|
||||
- Web
|
||||
- Mobile
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: GDevelop version
|
||||
description: |
|
||||
Which version of GDevelop are you using?
|
||||
Take a look here: [Editor Home - About GDevelop - "This version of GDevelop is: ~~~"]
|
||||
placeholder: 5.1.159? 5.1.160?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Platform info
|
||||
value: |
|
||||
<details>
|
||||
|
||||
*OS (e.g. Windows, Linux, macOS, Android, iOS)*
|
||||
>
|
||||
|
||||
*OS Version (e.g. Windows 10, macOS 10.15)*
|
||||
>
|
||||
|
||||
*Browser(For Web) (e.g. Chrome, Firefox, Safari)*
|
||||
>
|
||||
|
||||
*Device(For Mobile) (e.g. iPhone 12, Samsung Galaxy S21)*
|
||||
>
|
||||
|
||||
</details>
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context about the problem here.
|
22
.github/workflows/build-storybook.yml
vendored
22
.github/workflows/build-storybook.yml
vendored
@@ -17,23 +17,31 @@ jobs:
|
||||
build-storybook:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 50
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'newIDE/app/package-lock.json'
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.BUILD_STORYBOOK_AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.BUILD_STORYBOOK_AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 50
|
||||
|
||||
# Cache npm dependencies to speed up the workflow
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-newIDE-app-node_modules
|
||||
with:
|
||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
|
||||
|
||||
- name: Install newIDE dependencies
|
||||
run: npm install
|
||||
working-directory: newIDE/app
|
||||
|
14
.github/workflows/extract-translations.yml
vendored
14
.github/workflows/extract-translations.yml
vendored
@@ -11,12 +11,20 @@ jobs:
|
||||
extract-translations:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'newIDE/app/package-lock.json'
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# Cache npm dependencies to speed up the workflow
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-newIDE-app-node_modules
|
||||
with:
|
||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
|
||||
|
||||
- name: Install gettext
|
||||
run: sudo apt update && sudo apt install gettext -y
|
||||
|
42
.github/workflows/issues.yml
vendored
42
.github/workflows/issues.yml
vendored
@@ -3,17 +3,41 @@ on:
|
||||
issues:
|
||||
types: [opened]
|
||||
jobs:
|
||||
autoclose:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Autoclose issues about adding a bug without changing the bug report template
|
||||
uses: arkon/issue-closer-action@v1.1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
type: "body"
|
||||
regex: ".*Scroll down to '\\.\\.\\.\\.'.*"
|
||||
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any steps to reproduce the bug.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop.io/), the Discord chat or [read the documentation](https://wiki.gdevelop.io/gdevelop5/start) to learn more about GDevelop. Thanks!"
|
||||
- name: Autoclose known beta 105 web-app update bug
|
||||
uses: arkon/issue-closer-action@v1.1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
type: "body"
|
||||
regex: ".*_instance.getRawFloatProperty is not a function.*"
|
||||
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed as this seems to be a known bug. It can be solved by **closing entirely the web-app and opening it again**. This will allow the web-app to auto-update and the problem should be gone."
|
||||
- name: Autoclose known beta 114 web-app update bug
|
||||
uses: arkon/issue-closer-action@v1.1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
type: "body"
|
||||
regex: ".*getAssociatedSettings is not a function.*"
|
||||
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed as this seems to be a known bug. It can be solved by **closing entirely the web-app and opening it again**. This will allow the web-app to auto-update and the problem should be gone."
|
||||
autocomment:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.issue.body, 'The node to be removed is not a child of this node')
|
||||
steps:
|
||||
- name: Autocomment indications on bug if it looks like #3453
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hi @${{ github.actor }}!
|
||||
Thank you for taking the time to open an issue.
|
||||
- name: Autocomment indications on bug if it looks like #3453
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
body: |
|
||||
Hi @${{ github.actor }}!
|
||||
Thank you for taking the time to open an issue.
|
||||
|
||||
The solved issue #3453 mentioned a similar error, maybe it could help fix this new issue.
|
||||
The solved issue #3453 mentioned a similar error, maybe it could help fix this new issue.
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
68
.github/workflows/pull-requests.yml
vendored
68
.github/workflows/pull-requests.yml
vendored
@@ -1,53 +1,29 @@
|
||||
name: GDevelop Issues automatic workflow
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
types: [opened]
|
||||
jobs:
|
||||
read-locales-metadata:
|
||||
if: github.event.pull_request.title == '[Auto PR] Update translations'
|
||||
if: contains(github.event.pull_request.title, '[Auto PR] Update translations')
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
COMMENT_TITLE: "Translation ratio changes"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Read and format locales metadata
|
||||
env:
|
||||
BASE: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
LANS=($(git diff $BASE...$HEAD -- newIDE/app/src/locales/LocalesMetadata.js | grep -E "^\s+\"languageName" | sed -E "s/^ *\"languageName\": \"//g" | sed -E "s/\",//g" | sed -E "s/ /_/g"))
|
||||
ADDS=($(git diff $BASE...$HEAD -- newIDE/app/src/locales/LocalesMetadata.js | grep -E "^\+\s*\"translationRatio\"" | sed -E "s/^\+ *\"translationRatio\": //g"))
|
||||
SUBS=($(git diff $BASE...$HEAD -- newIDE/app/src/locales/LocalesMetadata.js | grep -E "^\-\s*\"translationRatio\"" | sed -E "s/^\- *\"translationRatio\": //g"))
|
||||
touch sumup.md
|
||||
echo "## $COMMENT_TITLE" >> sumup.md
|
||||
echo "" >> sumup.md
|
||||
echo "| Language | Change |" >> sumup.md
|
||||
echo "| --- | --- |" >> sumup.md
|
||||
for index in ${!ADDS[@]}; do
|
||||
DELTA=$(echo "scale=3; (${ADDS[index]} - ${SUBS[index]})*100/1" | bc)
|
||||
if (( $(echo "$DELTA == 0" | bc -l) )); then
|
||||
continue
|
||||
fi
|
||||
LANGUAGE=${LANS[index]//_/ }
|
||||
echo "| $LANGUAGE | $(printf "%1.3f" $DELTA) % |" >> sumup.md
|
||||
done
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: fc
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.number }}
|
||||
body-includes: ${{ env.COMMENT_TITLE }}
|
||||
- name: Autocomment pull request with sumup
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.number }}
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
edit-mode: replace
|
||||
body-path: "sumup.md"
|
||||
- name: Read and format locales metadata
|
||||
run: |
|
||||
LANS=($(git diff HEAD^ HEAD --unified=5 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\s+\"languageName" | sed -E "s/^ *\"languageName\": \"//g" | sed -E "s/\",//g" | sed -E "s/ /_/g"))
|
||||
ADDS=($(git diff HEAD^ HEAD --unified=0 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\+\s*\"translationRatio\"" | sed -E "s/^\+ *\"translationRatio\": //g"))
|
||||
SUBS=($(git diff HEAD^ HEAD --unified=0 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\-\s*\"translationRatio\"" | sed -E "s/^\- *\"translationRatio\": //g"))
|
||||
touch sumup.txt
|
||||
for index in ${!ADDS[@]}; do
|
||||
echo ${LANS[index]} | sed -E "s/_/ /g" >> sumup.txt
|
||||
DELTA=$(bc <<< "scale=2;(${ADDS[index]}-${SUBS[index]})*100/1")
|
||||
echo $DELTA % >> sumup.txt
|
||||
done
|
||||
- name: Store sumup in outputs
|
||||
id: sumup
|
||||
run: echo "::set-output name=sumupFileContent::$(cat sumup.txt)"
|
||||
- name: Autocomment pull request with sumup
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
issue-number: ${{ github.event.number }}
|
||||
body: ${{ steps.sumup.outputs.sumupFileContent}}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
16
.github/workflows/update-translations.yml
vendored
16
.github/workflows/update-translations.yml
vendored
@@ -14,12 +14,20 @@ jobs:
|
||||
update-translations:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'newIDE/app/package-lock.json'
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# Cache npm dependencies to speed up the workflow
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-newIDE-app-node_modules
|
||||
with:
|
||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
|
||||
|
||||
- name: Install gettext
|
||||
run: sudo apt update && sudo apt install gettext -y
|
||||
@@ -56,7 +64,7 @@ jobs:
|
||||
working-directory: newIDE/app
|
||||
|
||||
- name: Create a Pull Request with the changes
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
uses: peter-evans/create-pull-request@v3.10.1
|
||||
with:
|
||||
commit-message: Update translations [skip ci]
|
||||
branch: chore/update-translations
|
||||
|
@@ -1,3 +1,3 @@
|
||||
This is the directory where native or WebAssembly binaries of the C++ code of GDCore and GDJS are produced.
|
||||
|
||||
See GDevelop.js README for the instructions to compile after a change in the C++ source code.
|
||||
See GDevelop.js README for the instructions to compile after a change in the C++ source code.
|
@@ -1,5 +1,5 @@
|
||||
#This is the CMake file used to build GDevelop.
|
||||
#For more information, see the README.md file.
|
||||
#For more information, see the Readme.md file.
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_policy(SET CMP0011 NEW)
|
||||
|
@@ -38,7 +38,7 @@ void CommentEvent::SerializeTo(SerializerElement &element) const {
|
||||
.SetAttribute("textB", textB);
|
||||
|
||||
element.AddChild("comment").SetValue(com1);
|
||||
if (!com2.empty()) element.AddChild("comment2").SetValue(com2);
|
||||
element.AddChild("comment2").SetValue(com2);
|
||||
}
|
||||
|
||||
void CommentEvent::UnserializeFrom(gd::Project &project,
|
||||
@@ -53,9 +53,7 @@ void CommentEvent::UnserializeFrom(gd::Project &project,
|
||||
textB = colorElement.GetIntAttribute("textB");
|
||||
|
||||
com1 = element.GetChild("comment", 0, "Com1").GetValue().GetString();
|
||||
if (element.HasChild("comment2")) {
|
||||
com2 = element.GetChild("comment2", 0, "Com2").GetValue().GetString();
|
||||
}
|
||||
com2 = element.GetChild("comment2", 0, "Com2").GetValue().GetString();
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -289,7 +289,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
condition.SetParameters(parameters);
|
||||
}
|
||||
|
||||
// Verify that there are no mismatches between object type in parameters.
|
||||
// Verify that there are no mismatchs between object type in parameters.
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
|
||||
gd::String objectInParameter =
|
||||
@@ -481,7 +481,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
action.SetParameters(parameters);
|
||||
}
|
||||
|
||||
// Verify that there are no mismatches between object type in parameters.
|
||||
// Verify that there are no mismatchs between object type in parameters.
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
|
||||
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
|
||||
@@ -727,7 +727,6 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
metadata.GetType() == "tilemapResource" ||
|
||||
metadata.GetType() == "tilesetResource" ||
|
||||
metadata.GetType() == "videoResource" ||
|
||||
metadata.GetType() == "model3DResource" ||
|
||||
// Deprecated, old parameter names:
|
||||
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
|
||||
metadata.GetType() == "soundfile" || metadata.GetType() == "police") {
|
||||
@@ -1239,7 +1238,7 @@ size_t EventsCodeGenerator::GenerateSingleUsageUniqueIdFor(
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// Base the unique id on the address in memory so that the same instruction
|
||||
// Base the unique id on the adress in memory so that the same instruction
|
||||
// in memory will get the same id across different code generations.
|
||||
size_t uniqueId = (size_t)instruction;
|
||||
|
||||
|
@@ -507,7 +507,7 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
* - string : %Text expression -> string
|
||||
* - layer, color, file, stringWithSelector : Same as string
|
||||
* - relationalOperator : Used to make a comparison between the function
|
||||
return value and value of the parameter preceding the relationOperator
|
||||
resturn value and value of the parameter preceding the relationOperator
|
||||
parameter -> string
|
||||
* - operator : Used to update a value using a setter and a getter -> string
|
||||
* - key, mouse, objectvar, scenevar, globalvar, password, musicfile,
|
||||
@@ -785,7 +785,7 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
const gd::Project* project; ///< The project being used.
|
||||
const gd::Layout* scene; ///< The scene being generated.
|
||||
|
||||
bool errorOccurred; ///< Must be set to true if an error occurred.
|
||||
bool errorOccurred; ///< Must be set to true if an error occured.
|
||||
bool compilationForRuntime; ///< Is set to true if the code generation is
|
||||
///< made for runtime only.
|
||||
|
||||
|
@@ -51,8 +51,8 @@ gd::String ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootType);
|
||||
node->Visit(validator);
|
||||
if (!validator.GetFatalErrors().empty()) {
|
||||
std::cout << "Error: \"" << validator.GetFatalErrors()[0]->GetMessage()
|
||||
if (!validator.GetErrors().empty()) {
|
||||
std::cout << "Error: \"" << validator.GetErrors()[0]->GetMessage()
|
||||
<< "\" in: \"" << expression.GetPlainString() << "\" ("
|
||||
<< rootType << ")" << std::endl;
|
||||
|
||||
@@ -170,7 +170,7 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
}
|
||||
else {
|
||||
// This is for function names that are put in IdentifierNode
|
||||
// because the type is needed to tell them apart from variables.
|
||||
// because the type is needed to tell them appart from variables.
|
||||
output += GenerateDefaultValue(type);
|
||||
}
|
||||
}
|
||||
|
@@ -66,11 +66,6 @@ class GD_CORE_API ReadOnlyEventVisitor {
|
||||
* Note that VisitEvent is also called with this event.
|
||||
*/
|
||||
virtual void VisitLinkEvent(const gd::LinkEvent& linkEvent) = 0;
|
||||
|
||||
/**
|
||||
* @brief Abort the iteration on the events.
|
||||
*/
|
||||
virtual void StopAnyEventIteration() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
#include "EventsList.h"
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
@@ -101,8 +100,9 @@ bool EventsList::Contains(const gd::BaseEvent& eventToSearch,
|
||||
}
|
||||
|
||||
bool EventsList::MoveEventToAnotherEventsList(const gd::BaseEvent& eventToMove,
|
||||
gd::EventsList& newEventsList,
|
||||
std::size_t newPosition) {
|
||||
gd::EventsList& newEventsList,
|
||||
std::size_t newPosition) {
|
||||
|
||||
for (std::size_t i = 0; i < GetEventsCount(); ++i) {
|
||||
if (events[i].get() == &eventToMove) {
|
||||
std::shared_ptr<BaseEvent> event = events[i];
|
||||
|
@@ -33,7 +33,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
"res/function32.png",
|
||||
"res/function32.png")
|
||||
.SetHelpPath("/events/functions/return")
|
||||
.AddParameter("expression", _("The number to be returned"))
|
||||
.AddParameter("expression", "The number to be returned")
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
@@ -48,7 +48,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
"res/function32.png",
|
||||
"res/function32.png")
|
||||
.SetHelpPath("/events/functions/return")
|
||||
.AddParameter("string", _("The text to be returned"))
|
||||
.AddParameter("string", "The text to be returned")
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
@@ -62,37 +62,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
"res/function32.png",
|
||||
"res/function32.png")
|
||||
.SetHelpPath("/events/functions/return")
|
||||
.AddParameter("trueorfalse", _("Should the condition be true or false?"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("CopyArgumentToVariable",
|
||||
_("Copy function parameter to variable"),
|
||||
_("Copy a function parameter (also called \"argument\") to a variable. "
|
||||
"The parameter type must be a variable."),
|
||||
_("Copy the parameter _PARAM0_ into the variable _PARAM1_"),
|
||||
"",
|
||||
"res/function32.png",
|
||||
"res/function32.png")
|
||||
.SetHelpPath("/events/functions/return")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "variable")
|
||||
.AddParameter("scenevar", _("Scene variable"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("CopyVariableToArgument",
|
||||
_("Copy variable to function parameter"),
|
||||
_("Copy a variable to function parameter (also called \"argument\"). "
|
||||
"The parameter type must be a variable."),
|
||||
_("Copy the variable _PARAM1_ into the parameter _PARAM0_"),
|
||||
"",
|
||||
"res/function32.png",
|
||||
"res/function32.png")
|
||||
.SetHelpPath("/events/functions/return")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "variable")
|
||||
.AddParameter("scenevar", _("Scene variable"))
|
||||
.AddParameter("trueorfalse", "Should the condition be true or false?")
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
@@ -107,7 +77,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
"",
|
||||
"res/function32.png",
|
||||
"res/function32.png")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
|
||||
.AddParameter("functionParameterName", "Parameter name")
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
@@ -118,7 +88,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
_("Get function parameter (also called \"argument\") value."),
|
||||
"",
|
||||
"res/function16.png")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
|
||||
.AddParameter("functionParameterName", "Parameter name")
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
@@ -128,7 +98,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
_("Get function parameter (also called \"argument\") text."),
|
||||
"",
|
||||
"res/function16.png")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
|
||||
.AddParameter("functionParameterName", "Parameter name")
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
@@ -140,7 +110,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
"",
|
||||
"res/function32.png",
|
||||
"res/function16.png")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
|
||||
.AddParameter("functionParameterName", "Parameter name")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", gd::ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
@@ -154,7 +124,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
"",
|
||||
"res/function32.png",
|
||||
"res/function16.png")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
|
||||
.AddParameter("functionParameterName", "Parameter name")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string", gd::ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
@@ -1588,7 +1588,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"Raycast",
|
||||
_("Raycast"),
|
||||
_("Sends a ray from the given source position and angle, "
|
||||
"intersecting the closest object.\nThe intersected "
|
||||
"intersecting the closest object.\nThe instersected "
|
||||
"object will become the only one taken into account.\nIf "
|
||||
"the condition is inverted, the object to be intersected "
|
||||
"will be the farthest one within the ray radius."),
|
||||
@@ -1619,7 +1619,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"RaycastToPosition",
|
||||
_("Raycast to position"),
|
||||
_("Sends a ray from the given source position to the final point, "
|
||||
"intersecting the closest object.\nThe intersected "
|
||||
"intersecting the closest object.\nThe instersected "
|
||||
"object will become the only one taken into account.\nIf "
|
||||
"the condition is inverted, the object to be intersected "
|
||||
"will be the farthest one within the ray radius."),
|
||||
|
@@ -69,12 +69,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
extension
|
||||
.AddAction(
|
||||
"EcrireFichierExp",
|
||||
_("Save a value"),
|
||||
_("Save the result of the expression in the stored data, in the "
|
||||
_("Write a value"),
|
||||
_("Write the result of the expression in the stored data, in the "
|
||||
"specified element.\nSpecify the structure leading to the "
|
||||
"element using / (example : Root/Level/Current)\nSpaces are "
|
||||
"forbidden in element names."),
|
||||
_("Save _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
|
||||
_("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
|
||||
"",
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
@@ -85,12 +85,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
extension
|
||||
.AddAction(
|
||||
"EcrireFichierTxt",
|
||||
_("Save a text"),
|
||||
_("Save the text in the specified storage, in the specified "
|
||||
_("Write a text"),
|
||||
_("Write the text in the specified storage, in the specified "
|
||||
"element.\nSpecify "
|
||||
"the structure leading to the element using / (example : "
|
||||
"Root/Level/Current)\nSpaces are forbidden in element names."),
|
||||
_("Save _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
|
||||
_("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
|
||||
"",
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
@@ -101,13 +101,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
extension
|
||||
.AddAction(
|
||||
"LireFichierExp",
|
||||
_("Load a value"),
|
||||
_("Load the value saved in the specified element and store it in a "
|
||||
_("Read a value"),
|
||||
_("Read the value saved in the specified element and store it in a "
|
||||
"scene "
|
||||
"variable.\nSpecify the structure leading to the element using / "
|
||||
"(example : Root/Level/Current)\nSpaces are forbidden in element "
|
||||
"names."),
|
||||
_("Load _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
|
||||
_("Read _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
|
||||
"",
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
@@ -119,13 +119,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
extension
|
||||
.AddAction(
|
||||
"LireFichierTxt",
|
||||
_("Load a text"),
|
||||
_("Load the text saved in the specified element and store it in a "
|
||||
_("Read a text"),
|
||||
_("Read the text saved in the specified element and store it in a "
|
||||
"scene "
|
||||
"variable.\nSpecify the structure leading to the element using / "
|
||||
"(example : Root/Level/Current)\nSpaces are forbidden in element "
|
||||
"names."),
|
||||
_("Load _PARAM1_ from storage _PARAM0_ and store as text in "
|
||||
_("Read _PARAM1_ from storage _PARAM0_ and store as text in "
|
||||
"_PARAM3_"),
|
||||
"",
|
||||
"res/actions/fichier24.png",
|
||||
|
@@ -48,7 +48,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
|
||||
.AddParameter("string", "Content type", "", true)
|
||||
.SetParameterLongDescription(
|
||||
"If empty, \"application/x-www-form-urlencoded\" will be used.")
|
||||
.AddParameter("scenevar", "Response scene variable", "", true)
|
||||
.AddParameter("scenevar", "Reponse scene variable", "", true)
|
||||
.SetParameterLongDescription(
|
||||
"The response of the server will be stored, as a string, in this "
|
||||
"variable. If the server returns *JSON*, you may want to use the "
|
||||
|
@@ -54,19 +54,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
.AddCondition("DoesSceneExist",
|
||||
_("Does scene exist"),
|
||||
_("Check if scene exists."),
|
||||
_("Scene _PARAM1_ exists"),
|
||||
"",
|
||||
"res/actions/texte.png",
|
||||
"res/actions/texte.png")
|
||||
.SetHelpPath("/interface/scene-editor/events")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("sceneName", _("Name of the scene to check"))
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
.AddAction("Scene",
|
||||
_("Change the scene"),
|
||||
|
@@ -126,8 +126,8 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
||||
extension
|
||||
.AddExpression(
|
||||
"StrFindLast",
|
||||
_("Search the last occurrence in a text"),
|
||||
_("Search the last occurrence in a string (return the position of "
|
||||
_("Search the last occurence in a text"),
|
||||
_("Search the last occurence in a string (return the position of "
|
||||
"the result, from the beginning of the string, or -1 if not "
|
||||
"found)"),
|
||||
"",
|
||||
@@ -169,8 +169,8 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
||||
extension
|
||||
.AddExpression(
|
||||
"StrFindLastFrom",
|
||||
_("Search the last occurrence in a text, starting from a position"),
|
||||
_("Search in a text the last occurrence, starting from a position "
|
||||
_("Search the last occurence in a text, starting from a position"),
|
||||
_("Search in a text the last occurence, starting from a position "
|
||||
"(return "
|
||||
" the position of the result, from the beginning of the string, or "
|
||||
"-1 if not found)"),
|
||||
|
@@ -62,7 +62,7 @@ class GD_CORE_API DependencyMetadata {
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Sets the type of dependency (what will be used to install it)
|
||||
* \brief Sets the type of dependecy (what will be used to install it)
|
||||
*
|
||||
* This can either be "npm" or "cordova" for now.
|
||||
*/
|
||||
|
@@ -7,6 +7,9 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
EffectMetadata::EffectMetadata(const gd::String& type_)
|
||||
: type(type_), isMarkedAsNotWorkingForObjects(false) {}
|
||||
|
||||
EffectMetadata& EffectMetadata::SetIncludeFile(const gd::String& includeFile) {
|
||||
includeFiles.clear();
|
||||
includeFiles.push_back(includeFile);
|
||||
@@ -20,4 +23,9 @@ EffectMetadata& EffectMetadata::AddIncludeFile(const gd::String& includeFile) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
EffectMetadata& EffectMetadata::MarkAsNotWorkingForObjects() {
|
||||
isMarkedAsNotWorkingForObjects = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -3,8 +3,8 @@
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef EFFECTMETADATA_H
|
||||
#define EFFECTMETADATA_H
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -25,25 +25,21 @@ class GD_CORE_API EffectMetadata {
|
||||
/**
|
||||
* \brief Construct an effect metadata, with the given type
|
||||
*/
|
||||
EffectMetadata(const gd::String &type_)
|
||||
: type(type_), isMarkedAsNotWorkingForObjects(false),
|
||||
isMarkedAsOnlyWorkingFor2D(false), isMarkedAsOnlyWorkingFor3D(false),
|
||||
isMarkedAsUnique(false) {}
|
||||
EffectMetadata(const gd::String& type_);
|
||||
|
||||
/**
|
||||
* \brief Default constructor, only used for initializing
|
||||
* `badEffectMetadata`.
|
||||
*/
|
||||
EffectMetadata() {}
|
||||
/**
|
||||
* \brief Default constructor, only used for initializing `badEffectMetadata`.
|
||||
*/
|
||||
EffectMetadata() {}
|
||||
|
||||
virtual ~EffectMetadata(){};
|
||||
virtual ~EffectMetadata(){};
|
||||
|
||||
/**
|
||||
* \brief Set the name shown to the user.
|
||||
*/
|
||||
EffectMetadata &SetFullName(const gd::String &fullname_) {
|
||||
fullname = fullname_;
|
||||
return *this;
|
||||
/**
|
||||
* \brief Set the name shown to the user.
|
||||
*/
|
||||
EffectMetadata& SetFullName(const gd::String& fullname_) {
|
||||
fullname = fullname_;
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -73,6 +69,11 @@ class GD_CORE_API EffectMetadata {
|
||||
*/
|
||||
EffectMetadata& AddIncludeFile(const gd::String& includeFile);
|
||||
|
||||
/**
|
||||
* \brief Mark the effect as not working as an object effect.
|
||||
*/
|
||||
EffectMetadata& MarkAsNotWorkingForObjects();
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the properties of this effect.
|
||||
*/
|
||||
@@ -116,65 +117,10 @@ class GD_CORE_API EffectMetadata {
|
||||
return includeFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark the effect as not working as an object effect.
|
||||
*/
|
||||
EffectMetadata& MarkAsNotWorkingForObjects() {
|
||||
isMarkedAsNotWorkingForObjects = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark the effect as only working for the 2D renderer.
|
||||
*/
|
||||
EffectMetadata& MarkAsOnlyWorkingFor2D() {
|
||||
isMarkedAsOnlyWorkingFor2D = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark the effect as only working for the 3D renderer.
|
||||
*/
|
||||
EffectMetadata& MarkAsOnlyWorkingFor3D() {
|
||||
isMarkedAsOnlyWorkingFor3D = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark the effect as only addable once.
|
||||
*/
|
||||
EffectMetadata& MarkAsUnique() {
|
||||
isMarkedAsUnique = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the effect is marked as not working as an object effect.
|
||||
*/
|
||||
bool IsMarkedAsNotWorkingForObjects() const {
|
||||
return isMarkedAsNotWorkingForObjects;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Check if the effect is marked as only working for the 2D renderer.
|
||||
*/
|
||||
bool IsMarkedAsOnlyWorkingFor2D() const {
|
||||
return isMarkedAsOnlyWorkingFor2D;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Check if the effect is marked as only working for the 3D renderer.
|
||||
*/
|
||||
bool IsMarkedAsOnlyWorkingFor3D() const {
|
||||
return isMarkedAsOnlyWorkingFor3D;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Check if the effect can only be added once.
|
||||
*/
|
||||
bool IsMarkedAsUnique() const {
|
||||
return isMarkedAsUnique;
|
||||
};
|
||||
bool IsMarkedAsNotWorkingForObjects() const { return isMarkedAsNotWorkingForObjects; };
|
||||
|
||||
private:
|
||||
gd::String extensionNamespace;
|
||||
@@ -184,10 +130,8 @@ class GD_CORE_API EffectMetadata {
|
||||
gd::String description;
|
||||
std::vector<gd::String> includeFiles;
|
||||
bool isMarkedAsNotWorkingForObjects;
|
||||
bool isMarkedAsOnlyWorkingFor2D;
|
||||
bool isMarkedAsOnlyWorkingFor3D;
|
||||
bool isMarkedAsUnique;
|
||||
std::map<gd::String, gd::PropertyDescriptor> properties;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // EFFECTMETADATA_H
|
||||
|
@@ -57,7 +57,7 @@ class GD_CORE_API ObjectMetadata {
|
||||
|
||||
/**
|
||||
* \brief Construct an object metadata, with a function that will be called
|
||||
* to instantiate a new object.
|
||||
* to instanciate a new object.
|
||||
*/
|
||||
ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
const gd::String& name_,
|
||||
@@ -224,7 +224,7 @@ class GD_CORE_API ObjectMetadata {
|
||||
/**
|
||||
* \brief The "capabilities" that are offered by the base object that are
|
||||
* *not* supported by this object, and should be hidden in the editor
|
||||
* interface.
|
||||
* inferface.
|
||||
*/
|
||||
const std::set<gd::String>& GetUnsupportedBaseObjectCapabilities() const {
|
||||
return unsupportedBaseObjectCapabilities;
|
||||
@@ -232,7 +232,7 @@ class GD_CORE_API ObjectMetadata {
|
||||
|
||||
/**
|
||||
* \brief Add a "capability" that is offered by the base object that is *not*
|
||||
* supported by this object, and should be hidden in the editor interface.
|
||||
* supported by this object, and should be hidden in the editor inferface.
|
||||
*/
|
||||
ObjectMetadata& AddUnsupportedBaseObjectCapability(
|
||||
const gd::String& capability) {
|
||||
@@ -242,7 +242,7 @@ class GD_CORE_API ObjectMetadata {
|
||||
|
||||
/**
|
||||
* \brief Check if a "capability" that is offered by the base object is *not*
|
||||
* supported by this object, and should be hidden in the editor interface.
|
||||
* supported by this object, and should be hidden in the editor inferface.
|
||||
*/
|
||||
bool IsUnsupportedBaseObjectCapability(const gd::String& capability) const {
|
||||
return unsupportedBaseObjectCapabilities.find(capability) != unsupportedBaseObjectCapabilities.end();
|
||||
|
@@ -209,10 +209,10 @@ class GD_CORE_API ParameterMetadata {
|
||||
* \brief Return the expression type from the parameter type.
|
||||
* Declinations of "number" and "string" types (like "forceMultiplier" or
|
||||
* "sceneName") are replaced by "number" and "string".
|
||||
* \deprecated Use gd::ValueTypeMetadata or gd::GetExpressionPrimitiveValueType instead.
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
static const gd::String &GetExpressionValueType(const gd::String ¶meterType) {
|
||||
return gd::ValueTypeMetadata::GetExpressionPrimitiveValueType(parameterType);
|
||||
return gd::ValueTypeMetadata::GetPrimitiveValueType(parameterType);
|
||||
}
|
||||
|
||||
/** \name Serialization
|
||||
|
@@ -35,40 +35,17 @@ void ValueTypeMetadata::UnserializeFrom(const SerializerElement& element) {
|
||||
|
||||
const gd::String ValueTypeMetadata::numberType = "number";
|
||||
const gd::String ValueTypeMetadata::stringType = "string";
|
||||
const gd::String ValueTypeMetadata::variableType = "variable";
|
||||
const gd::String ValueTypeMetadata::booleanType = "boolean";
|
||||
|
||||
const gd::String &ValueTypeMetadata::GetExpressionPrimitiveValueType(
|
||||
const gd::String ¶meterType) {
|
||||
if (parameterType == "number" ||
|
||||
gd::ValueTypeMetadata::IsTypeExpression("number", parameterType)) {
|
||||
const gd::String &ValueTypeMetadata::GetPrimitiveValueType(const gd::String ¶meterType) {
|
||||
if (parameterType == "number" || gd::ValueTypeMetadata::IsTypeExpression("number", parameterType)) {
|
||||
return ValueTypeMetadata::numberType;
|
||||
}
|
||||
if (parameterType == "string" ||
|
||||
gd::ValueTypeMetadata::IsTypeExpression("string", parameterType)) {
|
||||
if (parameterType == "string" || gd::ValueTypeMetadata::IsTypeExpression("string", parameterType)) {
|
||||
return ValueTypeMetadata::stringType;
|
||||
}
|
||||
return parameterType;
|
||||
}
|
||||
|
||||
const gd::String &
|
||||
ValueTypeMetadata::GetPrimitiveValueType(const gd::String ¶meterType) {
|
||||
if (parameterType == "variable" ||
|
||||
gd::ValueTypeMetadata::IsTypeExpression("variable", parameterType)) {
|
||||
return ValueTypeMetadata::variableType;
|
||||
}
|
||||
if (parameterType == "boolean" || parameterType == "yesorno" ||
|
||||
parameterType == "trueorfalse") {
|
||||
return ValueTypeMetadata::booleanType;
|
||||
}
|
||||
// These 2 types are not strings from the code generator point of view,
|
||||
// but it is for event-based extensions.
|
||||
if (parameterType == "key" || parameterType == "mouse") {
|
||||
return ValueTypeMetadata::stringType;
|
||||
}
|
||||
return GetExpressionPrimitiveValueType(parameterType);
|
||||
}
|
||||
|
||||
const gd::String ValueTypeMetadata::numberValueType = "number";
|
||||
const gd::String ValueTypeMetadata::booleanValueType = "boolean";
|
||||
const gd::String ValueTypeMetadata::colorValueType = "color";
|
||||
|
@@ -178,16 +178,6 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
} else if (type == "variable") {
|
||||
return parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
parameterType == "scenevar";
|
||||
} else if (type == "resource") {
|
||||
return parameterType == "fontResource" ||
|
||||
parameterType == "soundfile" ||
|
||||
parameterType == "musicfile" ||
|
||||
parameterType == "bitmapFontResource" ||
|
||||
parameterType == "imageResource" ||
|
||||
parameterType == "jsonResource" ||
|
||||
parameterType == "tilemapResource" ||
|
||||
parameterType == "tilesetResource" ||
|
||||
parameterType == "model3DResource";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -196,23 +186,10 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
* \brief Return the expression type from the parameter type.
|
||||
* Declinations of "number" and "string" types (like "forceMultiplier" or
|
||||
* "sceneName") are replaced by "number" and "string".
|
||||
*
|
||||
* \note It only maps string and number types.
|
||||
*/
|
||||
static const gd::String &GetExpressionPrimitiveValueType(const gd::String ¶meterType);
|
||||
|
||||
/**
|
||||
* \brief Return the primitive type from the parameter type.
|
||||
* Declinations of "number" and "string" types (like "forceMultiplier" or
|
||||
* "sceneName") are replaced by "number" and "string".
|
||||
*
|
||||
* \note It also maps variable and boolean types.
|
||||
*/
|
||||
static const gd::String &GetPrimitiveValueType(const gd::String ¶meterType);
|
||||
static const gd::String numberType;
|
||||
static const gd::String stringType;
|
||||
static const gd::String variableType;
|
||||
static const gd::String booleanType;
|
||||
|
||||
/**
|
||||
* \brief Return the ValueTypeMetadata name for a property type.
|
||||
|
@@ -42,7 +42,7 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
*
|
||||
* You can also call then
|
||||
* DependenciesAnalyzer::ExternalEventsCanBeCompiledForAScene to check if the
|
||||
* external events can be compiled separately and called by a scene. \see
|
||||
* external events can be compiled separatly and called by a scene. \see
|
||||
* DependenciesAnalyzer::ExternalEventsCanBeCompiledForAScene
|
||||
*/
|
||||
DependenciesAnalyzer(const gd::Project& project_,
|
||||
|
@@ -84,9 +84,6 @@ void ReadOnlyArbitraryEventsWorker::VisitEventList(const gd::EventsList& events)
|
||||
DoVisitEventList(events);
|
||||
|
||||
for (std::size_t i = 0; i < events.size(); ++i) {
|
||||
if (shouldStopIteration) {
|
||||
break;
|
||||
}
|
||||
events[i].AcceptVisitor(*this);
|
||||
|
||||
if (events[i].CanHaveSubEvents()) {
|
||||
@@ -101,17 +98,11 @@ void ReadOnlyArbitraryEventsWorker::VisitEvent(const gd::BaseEvent& event) {
|
||||
const vector<const gd::InstructionsList*> conditionsVectors =
|
||||
event.GetAllConditionsVectors();
|
||||
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
|
||||
if (shouldStopIteration) {
|
||||
break;
|
||||
}
|
||||
VisitInstructionList(*conditionsVectors[j], true);
|
||||
}
|
||||
|
||||
const vector<const gd::InstructionsList*> actionsVectors = event.GetAllActionsVectors();
|
||||
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
|
||||
if (shouldStopIteration) {
|
||||
break;
|
||||
}
|
||||
VisitInstructionList(*actionsVectors[j], false);
|
||||
}
|
||||
}
|
||||
@@ -125,9 +116,6 @@ void ReadOnlyArbitraryEventsWorker::VisitInstructionList(
|
||||
DoVisitInstructionList(instructions, areConditions);
|
||||
|
||||
for (std::size_t i = 0; i < instructions.size(); ++i) {
|
||||
if (shouldStopIteration) {
|
||||
break;
|
||||
}
|
||||
VisitInstruction(instructions[i], areConditions);
|
||||
if (!instructions[i].GetSubInstructions().empty()) {
|
||||
VisitInstructionList(instructions[i].GetSubInstructions(),
|
||||
@@ -141,10 +129,6 @@ void ReadOnlyArbitraryEventsWorker::VisitInstruction(const gd::Instruction& inst
|
||||
DoVisitInstruction(instruction, isCondition);
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::StopAnyEventIteration() {
|
||||
shouldStopIteration = true;
|
||||
}
|
||||
|
||||
ReadOnlyArbitraryEventsWorkerWithContext::~ReadOnlyArbitraryEventsWorkerWithContext() {}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -144,7 +144,7 @@ class GD_CORE_API ArbitraryEventsWorkerWithContext
|
||||
*/
|
||||
class GD_CORE_API ReadOnlyArbitraryEventsWorker : private ReadOnlyEventVisitor {
|
||||
public:
|
||||
ReadOnlyArbitraryEventsWorker() : shouldStopIteration(false) {};
|
||||
ReadOnlyArbitraryEventsWorker(){};
|
||||
virtual ~ReadOnlyArbitraryEventsWorker();
|
||||
|
||||
/**
|
||||
@@ -152,9 +152,6 @@ class GD_CORE_API ReadOnlyArbitraryEventsWorker : private ReadOnlyEventVisitor {
|
||||
*/
|
||||
void Launch(const gd::EventsList& events) { VisitEventList(events); };
|
||||
|
||||
protected:
|
||||
void StopAnyEventIteration() override;
|
||||
|
||||
private:
|
||||
void VisitEventList(const gd::EventsList& events);
|
||||
void VisitEvent(const gd::BaseEvent& event) override;
|
||||
@@ -191,8 +188,6 @@ protected:
|
||||
*/
|
||||
virtual void DoVisitInstruction(const gd::Instruction& instruction,
|
||||
bool isCondition) {};
|
||||
|
||||
bool shouldStopIteration;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "EventsFunctionSelfCallChecker.h"
|
||||
|
||||
#include "GDCore/Events/Expression.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
#include "GDCore/Project/EventsFunction.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Check the type of the first condition or action.
|
||||
*/
|
||||
class GD_CORE_API FirstInstructionTypeChecker
|
||||
: public ReadOnlyArbitraryEventsWorker {
|
||||
public:
|
||||
FirstInstructionTypeChecker(const gd::String &eventFunctionType_,
|
||||
const bool isEventFunctionCondition_)
|
||||
: eventFunctionType(eventFunctionType_),
|
||||
isEventFunctionCondition(isEventFunctionCondition_),
|
||||
isOnlyCallingItself(false){};
|
||||
virtual ~FirstInstructionTypeChecker(){};
|
||||
|
||||
void DoVisitInstruction(const gd::Instruction &instruction,
|
||||
bool isCondition) override {
|
||||
if (isCondition == isEventFunctionCondition) {
|
||||
isOnlyCallingItself = instruction.GetType() == eventFunctionType;
|
||||
StopAnyEventIteration();
|
||||
}
|
||||
};
|
||||
|
||||
bool isOnlyCallingItself;
|
||||
|
||||
private:
|
||||
gd::String eventFunctionType;
|
||||
bool isEventFunctionCondition;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Check the type of the first condition or action.
|
||||
*/
|
||||
class GD_CORE_API FirstActionExpressionTypeChecker
|
||||
: public ReadOnlyArbitraryEventsWorker,
|
||||
ExpressionParser2NodeWorker {
|
||||
public:
|
||||
FirstActionExpressionTypeChecker(const gd::Platform &platform_,
|
||||
const gd::String &eventFunctionType_)
|
||||
: platform(platform_), eventFunctionType(eventFunctionType_),
|
||||
isOnlyCallingItself(false){};
|
||||
virtual ~FirstActionExpressionTypeChecker(){};
|
||||
|
||||
void DoVisitInstruction(const gd::Instruction &instruction,
|
||||
bool isCondition) override {
|
||||
// Typically, it should be a "return" action.
|
||||
if (!isCondition) {
|
||||
gd::String lastObjectParameter = "";
|
||||
const gd::InstructionMetadata &instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, instruction.GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
|
||||
if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType()) ||
|
||||
ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = instruction.GetParameter(pNb).GetRootNode();
|
||||
node->Visit(*this);
|
||||
}
|
||||
}
|
||||
StopAnyEventIteration();
|
||||
}
|
||||
}
|
||||
|
||||
// Only check expressions that directly calls a function.
|
||||
void OnVisitFunctionCallNode(FunctionCallNode &node) override {
|
||||
isOnlyCallingItself |= node.functionName == eventFunctionType;
|
||||
}
|
||||
|
||||
// Handle extra parenthesis.
|
||||
void OnVisitSubExpressionNode(SubExpressionNode &node) override {
|
||||
node.expression->Visit(*this);
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode &node) override {}
|
||||
// Handle sign that could have been forgotten
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode &node) override {
|
||||
node.factor->Visit(*this);
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode &node) override {}
|
||||
void OnVisitTextNode(TextNode &node) override {}
|
||||
void OnVisitVariableNode(VariableNode &node) override {}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode &node) override {}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode &node) override {}
|
||||
void OnVisitIdentifierNode(IdentifierNode &node) override {}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode &node) override {}
|
||||
void OnVisitEmptyNode(EmptyNode &node) override {}
|
||||
|
||||
bool isOnlyCallingItself;
|
||||
|
||||
private:
|
||||
const gd::Platform &platform;
|
||||
gd::String eventFunctionType;
|
||||
};
|
||||
|
||||
bool EventsFunctionSelfCallChecker::IsOnlyCallingItself(
|
||||
const gd::Project &project, const gd::String &functionFullType,
|
||||
const gd::EventsFunction &eventsFunction) {
|
||||
bool isOnlyCallingItself = false;
|
||||
|
||||
if (eventsFunction.IsExpression()) {
|
||||
FirstActionExpressionTypeChecker eventWorker(project.GetCurrentPlatform(),
|
||||
functionFullType);
|
||||
eventWorker.Launch(eventsFunction.GetEvents());
|
||||
isOnlyCallingItself = eventWorker.isOnlyCallingItself;
|
||||
} else {
|
||||
FirstInstructionTypeChecker eventWorker(functionFullType,
|
||||
!eventsFunction.IsAction());
|
||||
eventWorker.Launch(eventsFunction.GetEvents());
|
||||
isOnlyCallingItself = eventWorker.isOnlyCallingItself;
|
||||
}
|
||||
return isOnlyCallingItself;
|
||||
}
|
||||
|
||||
bool EventsFunctionSelfCallChecker::IsFreeFunctionOnlyCallingItself(
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsFunction &eventsFunction) {
|
||||
return IsOnlyCallingItself(
|
||||
project,
|
||||
PlatformExtension::GetEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(), eventsFunction.GetName()),
|
||||
eventsFunction);
|
||||
}
|
||||
|
||||
bool EventsFunctionSelfCallChecker::IsBehaviorFunctionOnlyCallingItself(
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::EventsFunction &eventsFunction) {
|
||||
return IsOnlyCallingItself(
|
||||
project,
|
||||
PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(), eventsBasedBehavior.GetName(),
|
||||
eventsFunction.GetName()),
|
||||
eventsFunction);
|
||||
}
|
||||
bool EventsFunctionSelfCallChecker::IsObjectFunctionOnlyCallingItself(
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsFunction &eventsFunction) {
|
||||
return IsOnlyCallingItself(project,
|
||||
PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
eventsFunction.GetName()),
|
||||
eventsFunction);
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/String.h"
|
||||
#include <vector>
|
||||
namespace gd {
|
||||
class Project;
|
||||
class EventsFunctionsExtension;
|
||||
class EventsFunctionsContainer;
|
||||
class EventsFunction;
|
||||
class EventsBasedBehavior;
|
||||
class EventsBasedObject;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
/**
|
||||
* \brief Check if functions are only calling themselves.
|
||||
*
|
||||
* It allows to detect mistakes when implementing functions for compatibility
|
||||
* after a function renaming.
|
||||
* Infinite loops can happens when the legacy function call itself instead of
|
||||
* the new function.
|
||||
*
|
||||
* \note Only the first instruction or the expressions of the first action is
|
||||
* checked.
|
||||
*/
|
||||
class GD_CORE_API EventsFunctionSelfCallChecker {
|
||||
public:
|
||||
/**
|
||||
* \brief Check if a free function is only calling itself.
|
||||
*/
|
||||
static bool IsFreeFunctionOnlyCallingItself(
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsFunction &eventsFunction);
|
||||
|
||||
/**
|
||||
* \brief Check if a behavior function is only calling itself.
|
||||
*/
|
||||
static bool IsBehaviorFunctionOnlyCallingItself(
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::EventsFunction &eventsFunction);
|
||||
|
||||
/**
|
||||
* \brief Check if an object function is only calling itself.
|
||||
*/
|
||||
static bool IsObjectFunctionOnlyCallingItself(
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsFunction &eventsFunction);
|
||||
|
||||
private:
|
||||
static bool IsOnlyCallingItself(const gd::Project &project,
|
||||
const gd::String &functionFullType,
|
||||
const gd::EventsFunction &eventsFunction);
|
||||
};
|
||||
} // namespace gd
|
@@ -77,43 +77,25 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
|
||||
MetadataProvider::GetBehaviorAnyExpressionMetadata(
|
||||
platform, behaviorType, function.functionName);
|
||||
|
||||
Type returnType = StringToType(metadata.GetReturnType());
|
||||
|
||||
if (!function.objectName.empty() &&
|
||||
!globalObjectsContainer.HasObjectNamed(function.objectName) &&
|
||||
!globalObjectsContainer.GetObjectGroups().Has(function.objectName) &&
|
||||
!objectsContainer.HasObjectNamed(function.objectName) &&
|
||||
!objectsContainer.GetObjectGroups().Has(function.objectName)) {
|
||||
RaiseTypeError(_("This object doesn't exist."),
|
||||
function.objectNameLocation, /*isFatal=*/false);
|
||||
return returnType;
|
||||
}
|
||||
|
||||
if (!function.behaviorName.empty() &&
|
||||
!gd::HasBehaviorInObjectOrGroup(globalObjectsContainer, objectsContainer,
|
||||
function.objectName,
|
||||
function.behaviorName)) {
|
||||
RaiseTypeError(_("This behavior is not attached to this object."),
|
||||
function.behaviorNameLocation, /*isFatal=*/false);
|
||||
return returnType;
|
||||
}
|
||||
|
||||
if (!function.objectName.empty() &&
|
||||
if (!function.objectName.empty()) {
|
||||
// If the function needs a capability on the object that may not be covered
|
||||
// by all objects, check it now.
|
||||
!metadata.GetRequiredBaseObjectCapability().empty()) {
|
||||
const gd::ObjectMetadata &objectMetadata =
|
||||
MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||
if (!metadata.GetRequiredBaseObjectCapability().empty()) {
|
||||
const gd::ObjectMetadata &objectMetadata =
|
||||
MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||
|
||||
if (objectMetadata.IsUnsupportedBaseObjectCapability(
|
||||
metadata.GetRequiredBaseObjectCapability())) {
|
||||
RaiseTypeError(
|
||||
_("This expression exists, but it can't be used on this object."),
|
||||
function.objectNameLocation);
|
||||
return returnType;
|
||||
if (objectMetadata.IsUnsupportedBaseObjectCapability(
|
||||
metadata.GetRequiredBaseObjectCapability())) {
|
||||
RaiseTypeError(
|
||||
_("This expression exists, but it can't be used on this object."),
|
||||
function.objectNameLocation);
|
||||
return StringToType(metadata.GetReturnType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Type returnType = StringToType(metadata.GetReturnType());
|
||||
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
|
||||
RaiseError(
|
||||
"invalid_function_name",
|
||||
@@ -133,8 +115,8 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
|
||||
"number to a string."),
|
||||
function.location);
|
||||
return returnType;
|
||||
} else if (parentType != Type::Number &&
|
||||
parentType != Type::NumberOrString) {
|
||||
}
|
||||
else if (parentType != Type::Number && parentType != Type::NumberOrString) {
|
||||
RaiseTypeError(_("You tried to use an expression that returns a "
|
||||
"number, but another type is expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
@@ -149,8 +131,8 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
|
||||
"string to a number."),
|
||||
function.location);
|
||||
return returnType;
|
||||
} else if (parentType != Type::String &&
|
||||
parentType != Type::NumberOrString) {
|
||||
}
|
||||
else if (parentType != Type::String && parentType != Type::NumberOrString) {
|
||||
RaiseTypeError(_("You tried to use an expression that returns a "
|
||||
"string, but another type is expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
@@ -190,7 +172,8 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
|
||||
_("You have not entered enough parameters for the expression.") + " " +
|
||||
expectedCountMessage,
|
||||
function.location);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
RaiseError(
|
||||
"extra_parameter",
|
||||
_("This parameter was not expected by this expression. Remove it "
|
||||
@@ -234,7 +217,8 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
|
||||
"parameter."),
|
||||
parameter->location);
|
||||
}
|
||||
} else if (gd::ParameterMetadata::IsObject(expectedParameterType)) {
|
||||
}
|
||||
else if (gd::ParameterMetadata::IsObject(expectedParameterType)) {
|
||||
if (dynamic_cast<IdentifierNode *>(parameter.get()) == nullptr) {
|
||||
RaiseError(
|
||||
"malformed_object_parameter",
|
||||
|
@@ -45,7 +45,7 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
|
||||
/**
|
||||
* \brief Helper function to check if a given node does not contain
|
||||
* any error including non-fatal ones.
|
||||
* any error.
|
||||
*/
|
||||
static bool HasNoErrors(const gd::Platform &platform,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
@@ -54,25 +54,16 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
gd::ExpressionNode& node) {
|
||||
gd::ExpressionValidator validator(platform, globalObjectsContainer, objectsContainer, rootType);
|
||||
node.Visit(validator);
|
||||
return validator.GetAllErrors().empty();
|
||||
return validator.GetErrors().empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get only the fatal errors
|
||||
*
|
||||
* Expressions with fatal error can't be generated.
|
||||
*/
|
||||
const std::vector<ExpressionParserDiagnostic*>& GetFatalErrors() {
|
||||
return fatalErrors;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Get all the errors
|
||||
*
|
||||
* No errors means that the expression is valid.
|
||||
*/
|
||||
const std::vector<ExpressionParserDiagnostic*>& GetAllErrors() {
|
||||
return allErrors;
|
||||
const std::vector<ExpressionParserDiagnostic*>& GetErrors() {
|
||||
return errors;
|
||||
};
|
||||
|
||||
protected:
|
||||
@@ -159,29 +150,12 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
void OnVisitNumberNode(NumberNode& node) override {
|
||||
ReportAnyError(node);
|
||||
childType = Type::Number;
|
||||
if (parentType == Type::String) {
|
||||
RaiseTypeError(
|
||||
_("You entered a number, but a text was expected (in quotes)."),
|
||||
node.location);
|
||||
} else if (parentType != Type::Number &&
|
||||
parentType != Type::NumberOrString) {
|
||||
RaiseTypeError(_("You entered a number, but this type was expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
node.location);
|
||||
}
|
||||
CheckType(parentType, childType, node.location);
|
||||
}
|
||||
void OnVisitTextNode(TextNode& node) override {
|
||||
ReportAnyError(node);
|
||||
childType = Type::String;
|
||||
if (parentType == Type::Number) {
|
||||
RaiseTypeError(_("You entered a text, but a number was expected."),
|
||||
node.location);
|
||||
} else if (parentType != Type::String &&
|
||||
parentType != Type::NumberOrString) {
|
||||
RaiseTypeError(_("You entered a text, but this type was expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
node.location);
|
||||
}
|
||||
CheckType(parentType, childType, node.location);
|
||||
}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
ReportAnyError(node);
|
||||
@@ -189,21 +163,7 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
node.child->Visit(*this);
|
||||
}
|
||||
childType = Type::Variable;
|
||||
if (parentType == Type::String) {
|
||||
RaiseTypeError(_("Variables must be surrounded by VariableString()."),
|
||||
node.location);
|
||||
} else if (parentType == Type::Number) {
|
||||
RaiseTypeError(_("Variables must be surrounded by Variable()."),
|
||||
node.location);
|
||||
} else if (parentType == Type::NumberOrString) {
|
||||
RaiseTypeError(
|
||||
_("Variables must be surrounded by Variable() or VariableString()."),
|
||||
node.location);
|
||||
} else if (parentType != Type::Variable) {
|
||||
RaiseTypeError(_("You entered a variable, but this type was expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
node.location);
|
||||
}
|
||||
CheckType(parentType, childType, node.location);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
ReportAnyError(node);
|
||||
@@ -279,26 +239,20 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
enum Type {Unknown = 0, Number, String, NumberOrString, Variable, Object, Empty};
|
||||
Type ValidateFunction(const gd::FunctionCallNode& function);
|
||||
|
||||
void ReportAnyError(const ExpressionNode& node, bool isFatal = true) {
|
||||
void ReportAnyError(const ExpressionNode& node) {
|
||||
if (node.diagnostic && node.diagnostic->IsError()) {
|
||||
// Syntax errors are holden by the AST nodes.
|
||||
// It's fine to give pointers on them as the AST live longer than errors
|
||||
// handling.
|
||||
allErrors.push_back(node.diagnostic.get());
|
||||
if (isFatal) {
|
||||
fatalErrors.push_back(node.diagnostic.get());
|
||||
}
|
||||
errors.push_back(node.diagnostic.get());
|
||||
}
|
||||
}
|
||||
|
||||
void RaiseError(const gd::String &type,
|
||||
const gd::String &message, const ExpressionParserLocation &location, bool isFatal = true) {
|
||||
const gd::String &message, const ExpressionParserLocation &location) {
|
||||
auto diagnostic = gd::make_unique<ExpressionParserError>(
|
||||
type, message, location);
|
||||
allErrors.push_back(diagnostic.get());
|
||||
if (isFatal) {
|
||||
fatalErrors.push_back(diagnostic.get());
|
||||
}
|
||||
errors.push_back(diagnostic.get());
|
||||
// Errors found by the validator are not holden by the AST nodes.
|
||||
// They must be owned by the validator to keep living while errors are
|
||||
// handled by the caller.
|
||||
@@ -306,8 +260,8 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
}
|
||||
|
||||
void RaiseTypeError(
|
||||
const gd::String &message, const ExpressionParserLocation &location, bool isFatal = true) {
|
||||
RaiseError("type_error", message, location, isFatal);
|
||||
const gd::String &message, const ExpressionParserLocation &location) {
|
||||
RaiseError("type_error", message, location);
|
||||
}
|
||||
|
||||
void RaiseOperatorError(
|
||||
@@ -315,6 +269,32 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
RaiseError("invalid_operator", message, location);
|
||||
}
|
||||
|
||||
void CheckType(Type expect, Type actual, const ExpressionParserLocation &location) {
|
||||
if (actual == Type::String) {
|
||||
if (expect == Type::Number) {
|
||||
RaiseTypeError(_("You entered a text, but a number was expected."),
|
||||
location);
|
||||
}
|
||||
else if (expect != Type::String && expect != Type::NumberOrString) {
|
||||
RaiseTypeError(
|
||||
_("You entered a text, but this type was expected:") + " " + TypeToString(expect),
|
||||
location);
|
||||
}
|
||||
}
|
||||
else if (actual == Type::Number) {
|
||||
if (expect == Type::String) {
|
||||
RaiseTypeError(
|
||||
_("You entered a number, but a text was expected (in quotes)."),
|
||||
location);
|
||||
}
|
||||
else if (expect != Type::Number && expect != Type::NumberOrString) {
|
||||
RaiseTypeError(
|
||||
_("You entered a number, but this type was expected:") + " " + TypeToString(expect),
|
||||
location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Type StringToType(const gd::String &type);
|
||||
static const gd::String &TypeToString(Type type);
|
||||
static const gd::String unknownTypeString;
|
||||
@@ -326,8 +306,7 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
static const gd::String identifierTypeString;
|
||||
static const gd::String emptyTypeString;
|
||||
|
||||
std::vector<ExpressionParserDiagnostic*> fatalErrors;
|
||||
std::vector<ExpressionParserDiagnostic*> allErrors;
|
||||
std::vector<ExpressionParserDiagnostic*> errors;
|
||||
std::vector<std::unique_ptr<ExpressionParserDiagnostic>> supplementalErrors;
|
||||
Type childType;
|
||||
Type parentType;
|
||||
|
@@ -82,7 +82,7 @@ bool UsedExtensionsFinder::DoVisitInstruction(gd::Instruction& instruction,
|
||||
|
||||
// Expressions scanner
|
||||
|
||||
// Ignore literals nodes
|
||||
// Ignore litterals nodes
|
||||
void UsedExtensionsFinder::OnVisitNumberNode(NumberNode& node){};
|
||||
void UsedExtensionsFinder::OnVisitTextNode(TextNode& node){};
|
||||
|
||||
|
@@ -144,7 +144,7 @@ void ExtensionsLoader::LoadExtension(const gd::String &fullpath,
|
||||
bool forgiving) {
|
||||
if (platform.GetExtensionCreateFunctionName().empty()) {
|
||||
cout << "Unable to load extension " << fullpath << ":" << endl;
|
||||
cout << "The platform does not support extensions creation." << endl;
|
||||
cout << "The plaftorm does not support extensions creation." << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -35,7 +35,7 @@ class GD_CORE_API ExtensionsLoader {
|
||||
* \param platform The platform the extensions belongs to.
|
||||
* \param forgiving If set to true, files will try to be opened, but a failure
|
||||
* when searching for the platform creation function symbol won't be logged as
|
||||
* an error. (All other errors are still reported as usual).
|
||||
* an error. (All other errors are still reparted as usual).
|
||||
*
|
||||
* \note Extensions files must have extensions *.xgd(w|l|m)(e),
|
||||
* w for Windows, l for Linux, m for Mac, e for Edittime extensions.
|
||||
@@ -51,7 +51,7 @@ class GD_CORE_API ExtensionsLoader {
|
||||
* \param platform The platform the extension belongs to.
|
||||
* \param forgiving If set to true, files will try to be opened, but a failure
|
||||
* when searching for the platform creation function symbol won't be logged as
|
||||
* an error. (All other errors are still reported as usual).
|
||||
* an error. (All other errors are still reparted as usual).
|
||||
*/
|
||||
static void LoadExtension(const gd::String& fullpath,
|
||||
gd::Platform& platform,
|
||||
|
@@ -45,11 +45,6 @@ void ArbitraryResourceWorker::ExposeTileset(gd::String& tilesetName){
|
||||
// do.
|
||||
};
|
||||
|
||||
void ArbitraryResourceWorker::ExposeModel3D(gd::String& resourceName){
|
||||
// Nothing to do by default - each child class can define here the action to
|
||||
// do.
|
||||
};
|
||||
|
||||
void ArbitraryResourceWorker::ExposeVideo(gd::String& videoName){
|
||||
// Nothing to do by default - each child class can define here the action to
|
||||
// do.
|
||||
@@ -71,7 +66,7 @@ void ArbitraryResourceWorker::ExposeAudio(gd::String& audioName) {
|
||||
}
|
||||
}
|
||||
|
||||
// For compatibility with older projects (where events were referring to files
|
||||
// For compatibility with older projects (where events were refering to files
|
||||
// directly), we consider that this resource name is a filename, and so expose
|
||||
// it as a file.
|
||||
ExposeFile(audioName);
|
||||
@@ -88,7 +83,7 @@ void ArbitraryResourceWorker::ExposeFont(gd::String& fontName) {
|
||||
}
|
||||
}
|
||||
|
||||
// For compatibility with older projects (where events were referring to files
|
||||
// For compatibility with older projects (where events were refering to files
|
||||
// directly), we consider that this resource name is a filename, and so expose
|
||||
// it as a file.
|
||||
ExposeFile(fontName);
|
||||
@@ -151,8 +146,6 @@ void ArbitraryResourceWorker::ExposeEmbeddeds(gd::String& resourceName) {
|
||||
ExposeTileset(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "video") {
|
||||
ExposeVideo(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "model3D") {
|
||||
ExposeModel3D(potentiallyUpdatedTargetResourceName);
|
||||
}
|
||||
|
||||
if (potentiallyUpdatedTargetResourceName != targetResourceName) {
|
||||
@@ -240,10 +233,6 @@ class ResourceWorkerInEventsWorker : public ArbitraryEventsWorker {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeTileset(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "model3DResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeModel3D(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -85,11 +85,6 @@ class GD_CORE_API ArbitraryResourceWorker {
|
||||
*/
|
||||
virtual void ExposeTileset(gd::String &tilesetName);
|
||||
|
||||
/**
|
||||
* \brief Expose a 3D model, which is always a reference to a "model3D" resource.
|
||||
*/
|
||||
virtual void ExposeModel3D(gd::String &resourceName);
|
||||
|
||||
/**
|
||||
* \brief Expose a video, which is always a reference to a "video" resource.
|
||||
*/
|
||||
|
@@ -29,7 +29,7 @@ bool ProjectResourcesCopier::CopyAllResourcesTo(
|
||||
originalProject.ExposeResources(absolutePathChecker);
|
||||
|
||||
auto projectDirectory = fs.DirNameFrom(originalProject.GetProjectFile());
|
||||
std::cout << "Copying all resources from " << projectDirectory << " to "
|
||||
std::cout << "Copying all ressources from " << projectDirectory << " to "
|
||||
<< destinationDirectory << "..." << std::endl;
|
||||
|
||||
// Get the resources to be copied
|
||||
|
@@ -44,7 +44,6 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
|
||||
std::set<gd::String>& GetAllTilesets() { return GetAll("tileset"); };
|
||||
std::set<gd::String>& GetAllVideos() { return GetAll("video"); };
|
||||
std::set<gd::String>& GetAllBitmapFonts() { return GetAll("bitmapFont"); };
|
||||
std::set<gd::String>& GetAll3DModels() { return GetAll("model3D"); };
|
||||
std::set<gd::String>& GetAll(const gd::String& resourceType) {
|
||||
if (resourceType == "image") return allImages;
|
||||
if (resourceType == "audio") return allAudios;
|
||||
@@ -54,7 +53,6 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
|
||||
if (resourceType == "tileset") return allTilesets;
|
||||
if (resourceType == "video") return allVideos;
|
||||
if (resourceType == "bitmapFont") return allBitmapFonts;
|
||||
if (resourceType == "model3D") return allModel3Ds;
|
||||
|
||||
return emptyResources;
|
||||
};
|
||||
@@ -86,9 +84,6 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
|
||||
virtual void ExposeBitmapFont(gd::String& bitmapFontResourceName) override {
|
||||
allBitmapFonts.insert(bitmapFontResourceName);
|
||||
};
|
||||
virtual void ExposeModel3D(gd::String& resourceName) override {
|
||||
allModel3Ds.insert(resourceName);
|
||||
};
|
||||
|
||||
protected:
|
||||
std::set<gd::String> allImages;
|
||||
@@ -99,7 +94,6 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
|
||||
std::set<gd::String> allTilesets;
|
||||
std::set<gd::String> allVideos;
|
||||
std::set<gd::String> allBitmapFonts;
|
||||
std::set<gd::String> allModel3Ds;
|
||||
std::set<gd::String> emptyResources;
|
||||
};
|
||||
|
||||
|
@@ -59,9 +59,6 @@ class ResourcesRenamer : public gd::ArbitraryResourceWorker {
|
||||
virtual void ExposeBitmapFont(gd::String& bitmapFontName) override {
|
||||
RenameIfNeeded(bitmapFontName);
|
||||
};
|
||||
virtual void ExposeModel3D(gd::String& resourceName) override {
|
||||
RenameIfNeeded(resourceName);
|
||||
};
|
||||
|
||||
private:
|
||||
void RenameIfNeeded(gd::String& resourceName) {
|
||||
|
@@ -16,7 +16,7 @@ class EventsBasedObject;
|
||||
class AbstractEventsBasedEntity;
|
||||
class PropertyDescriptor;
|
||||
class NamedPropertyDescriptor;
|
||||
} // namespace gd
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -24,24 +24,22 @@ namespace gd {
|
||||
* \brief Generate a getter and a setter functions for properties.
|
||||
*/
|
||||
class GD_CORE_API PropertyFunctionGenerator {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* \brief Generate a getter and a setter for the given behavior property.
|
||||
*/
|
||||
static void GenerateBehaviorGetterAndSetter(
|
||||
gd::Project &project,
|
||||
gd::EventsFunctionsExtension &extension,
|
||||
gd::Project &project, gd::EventsFunctionsExtension &extension,
|
||||
gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::NamedPropertyDescriptor &property,
|
||||
bool isSharedProperties);
|
||||
const gd::NamedPropertyDescriptor &property, bool isSharedProperties);
|
||||
/**
|
||||
* \brief Generate a getter and a setter for the given object property.
|
||||
*/
|
||||
static void GenerateObjectGetterAndSetter(
|
||||
gd::Project &project,
|
||||
gd::EventsFunctionsExtension &extension,
|
||||
gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::NamedPropertyDescriptor &property);
|
||||
static void
|
||||
GenerateObjectGetterAndSetter(gd::Project &project,
|
||||
gd::EventsFunctionsExtension &extension,
|
||||
gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::NamedPropertyDescriptor &property);
|
||||
static bool CanGenerateGetterAndSetter(
|
||||
const gd::AbstractEventsBasedEntity &eventsBasedEntity,
|
||||
const gd::NamedPropertyDescriptor &property);
|
||||
@@ -52,26 +50,23 @@ class GD_CORE_API PropertyFunctionGenerator {
|
||||
static void GenerateConditionSkeleton(gd::Project &project,
|
||||
gd::EventsFunction &eventFunction);
|
||||
|
||||
~PropertyFunctionGenerator(){};
|
||||
~PropertyFunctionGenerator();
|
||||
|
||||
private:
|
||||
private:
|
||||
static void GenerateGetterAndSetter(
|
||||
gd::Project &project,
|
||||
gd::EventsFunctionsExtension &extension,
|
||||
gd::Project &project, gd::EventsFunctionsExtension &extension,
|
||||
gd::AbstractEventsBasedEntity &eventsBasedEntity,
|
||||
const gd::NamedPropertyDescriptor &property,
|
||||
const gd::String &objectType,
|
||||
bool isBehavior,
|
||||
bool isSharedProperties);
|
||||
const gd::NamedPropertyDescriptor &property, const gd::String &objectType,
|
||||
bool isBehavior, bool isSharedProperties);
|
||||
|
||||
static gd::String CapitalizeFirstLetter(const gd::String &string);
|
||||
static gd::String UnCapitalizeFirstLetter(const gd::String &string);
|
||||
static gd::String GetStringifiedExtraInfo(
|
||||
const gd::PropertyDescriptor &property);
|
||||
static gd::String
|
||||
GetStringifiedExtraInfo(const gd::PropertyDescriptor &property);
|
||||
|
||||
PropertyFunctionGenerator();
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_PROPERTYFUNCTIONGENERATOR_H
|
||||
#endif // GDCORE_PROPERTYFUNCTIONGENERATOR_H
|
||||
|
@@ -845,21 +845,9 @@ void WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
return;
|
||||
};
|
||||
|
||||
AddRequiredBehaviorsFor(project, object, behaviorName);
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::AddRequiredBehaviorsFor(
|
||||
gd::Project& project,
|
||||
gd::Object& object,
|
||||
const gd::String& behaviorName) {
|
||||
if (!object.HasBehaviorNamed(behaviorName)) {
|
||||
return;
|
||||
};
|
||||
gd::Behavior& behavior = object.GetBehavior(behaviorName);
|
||||
|
||||
const gd::Platform& platform = project.GetCurrentPlatform();
|
||||
const gd::BehaviorMetadata& behaviorMetadata =
|
||||
MetadataProvider::GetBehaviorMetadata(platform, behavior.GetTypeName());
|
||||
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
|
||||
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
// Should not happen because the behavior was added successfully (so its
|
||||
// metadata are valid) - but double check anyway and bail out if the
|
||||
@@ -867,6 +855,7 @@ void WholeProjectRefactorer::AddRequiredBehaviorsFor(
|
||||
return;
|
||||
}
|
||||
|
||||
gd::Behavior& behavior = object.GetBehavior(behaviorName);
|
||||
for (auto const& keyValue : behavior.GetProperties()) {
|
||||
const gd::String& propertyName = keyValue.first;
|
||||
const gd::PropertyDescriptor& property = keyValue.second;
|
||||
@@ -1393,12 +1382,25 @@ void WholeProjectRefactorer::ObjectOrGroupRemovedInLayout(
|
||||
|
||||
// Remove object in external events
|
||||
if (removeEventsAndGroups) {
|
||||
for (auto &externalEventsName :
|
||||
GetAssociatedExternalEvents(project, layout.GetName())) {
|
||||
auto &externalEvents = project.GetExternalEvents(externalEventsName);
|
||||
gd::EventsRefactorer::RemoveObjectInEvents(
|
||||
project.GetCurrentPlatform(), project, layout,
|
||||
externalEvents.GetEvents(), objectName);
|
||||
DependenciesAnalyzer analyzer(project, layout);
|
||||
if (analyzer.Analyze()) {
|
||||
for (auto& externalEventsName :
|
||||
analyzer.GetExternalEventsDependencies()) {
|
||||
auto& externalEvents = project.GetExternalEvents(externalEventsName);
|
||||
gd::EventsRefactorer::RemoveObjectInEvents(project.GetCurrentPlatform(),
|
||||
project,
|
||||
layout,
|
||||
externalEvents.GetEvents(),
|
||||
objectName);
|
||||
}
|
||||
for (auto& layoutName : analyzer.GetScenesDependencies()) {
|
||||
auto& layout = project.GetLayout(layoutName);
|
||||
gd::EventsRefactorer::RemoveObjectInEvents(project.GetCurrentPlatform(),
|
||||
project,
|
||||
layout,
|
||||
layout.GetEvents(),
|
||||
objectName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1437,12 +1439,26 @@ void WholeProjectRefactorer::ObjectOrGroupRenamedInLayout(
|
||||
}
|
||||
|
||||
// Rename object in external events
|
||||
for (auto &externalEventsName :
|
||||
GetAssociatedExternalEvents(project, layout.GetName())) {
|
||||
auto &externalEvents = project.GetExternalEvents(externalEventsName);
|
||||
gd::EventsRefactorer::RenameObjectInEvents(
|
||||
project.GetCurrentPlatform(), project, layout,
|
||||
externalEvents.GetEvents(), oldName, newName);
|
||||
DependenciesAnalyzer analyzer(project, layout);
|
||||
if (analyzer.Analyze()) {
|
||||
for (auto& externalEventsName : analyzer.GetExternalEventsDependencies()) {
|
||||
auto& externalEvents = project.GetExternalEvents(externalEventsName);
|
||||
gd::EventsRefactorer::RenameObjectInEvents(project.GetCurrentPlatform(),
|
||||
project,
|
||||
layout,
|
||||
externalEvents.GetEvents(),
|
||||
oldName,
|
||||
newName);
|
||||
}
|
||||
for (auto& layoutName : analyzer.GetScenesDependencies()) {
|
||||
auto& layout = project.GetLayout(layoutName);
|
||||
gd::EventsRefactorer::RenameObjectInEvents(project.GetCurrentPlatform(),
|
||||
project,
|
||||
layout,
|
||||
layout.GetEvents(),
|
||||
oldName,
|
||||
newName);
|
||||
}
|
||||
}
|
||||
|
||||
// Rename object in external layouts
|
||||
|
@@ -212,13 +212,6 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
gd::Object& object,
|
||||
const gd::String& behaviorType,
|
||||
const gd::String& behaviorName);
|
||||
/**
|
||||
* \brief Add required behaviors if necessary to fill every behavior
|
||||
* properties of the given behaviors.
|
||||
*/
|
||||
static void AddRequiredBehaviorsFor(gd::Project& project,
|
||||
gd::Object& object,
|
||||
const gd::String& behaviorName);
|
||||
|
||||
/**
|
||||
* \brief Find every behavior of the object that needs the given behaviors
|
||||
@@ -332,7 +325,7 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
* \brief Refactor the project after an object is renamed in a layout
|
||||
*
|
||||
* This will update the layout, all external layouts associated with it
|
||||
* and all external events associated with it.
|
||||
* and all external events used by the layout.
|
||||
*/
|
||||
static void ObjectOrGroupRenamedInLayout(gd::Project& project,
|
||||
gd::Layout& layout,
|
||||
@@ -344,7 +337,7 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
* \brief Refactor the project after an object is removed in a layout
|
||||
*
|
||||
* This will update the layout, all external layouts associated with it
|
||||
* and all external events associated with it.
|
||||
* and all external events used by the layout.
|
||||
*/
|
||||
static void ObjectOrGroupRemovedInLayout(gd::Project& project,
|
||||
gd::Layout& layout,
|
||||
|
@@ -64,7 +64,7 @@ class GD_CORE_API EffectsContainer {
|
||||
std::size_t GetEffectPosition(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Return the number of effects.
|
||||
* Return the number of effecst.
|
||||
*/
|
||||
std::size_t GetEffectsCount() const;
|
||||
|
||||
|
@@ -217,7 +217,7 @@ class GD_CORE_API EventsFunction {
|
||||
bool IsAsync() const { return isAsync; }
|
||||
|
||||
/**
|
||||
* \brief Sets the asynchronicity of the function.
|
||||
* \brief Sets the asycronity of the function.
|
||||
*/
|
||||
EventsFunction& SetAsync(bool _isAsync) {
|
||||
isAsync = _isAsync;
|
||||
|
@@ -193,6 +193,7 @@ class GD_CORE_API InitialInstance {
|
||||
* \see gd::Object
|
||||
*/
|
||||
///@{
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief Return a map containing the properties names (as keys) and their
|
||||
* values.
|
||||
@@ -212,6 +213,7 @@ class GD_CORE_API InitialInstance {
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& layout);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Get the value of a double property stored in the instance.
|
||||
|
@@ -14,17 +14,7 @@ namespace gd {
|
||||
Camera Layer::badCamera;
|
||||
|
||||
Layer::Layer()
|
||||
: renderingType(""),
|
||||
isVisible(true),
|
||||
isLocked(false),
|
||||
isLightingLayer(false),
|
||||
followBaseLayerCamera(false),
|
||||
camera3DNearPlaneDistance(0.1),
|
||||
camera3DFarPlaneDistance(10000),
|
||||
camera3DFieldOfView(45),
|
||||
ambientLightColorR(200),
|
||||
ambientLightColorG(200),
|
||||
ambientLightColorB(200) {}
|
||||
: isVisible(true), isLightingLayer(false), followBaseLayerCamera(false) {}
|
||||
|
||||
/**
|
||||
* Change cameras count, automatically adding/removing them.
|
||||
@@ -36,21 +26,15 @@ void Layer::SetCameraCount(std::size_t n) {
|
||||
cameras.erase(cameras.begin() + cameras.size() - 1);
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void Layer::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("name", GetName());
|
||||
element.SetAttribute("renderingType", GetRenderingType());
|
||||
element.SetAttribute("visibility", GetVisibility());
|
||||
element.SetAttribute("isLocked", IsLocked());
|
||||
element.SetAttribute("isLightingLayer", IsLightingLayer());
|
||||
element.SetAttribute("followBaseLayerCamera", IsFollowingBaseLayerCamera());
|
||||
element.SetAttribute("ambientLightColorR", (int)GetAmbientLightColorRed());
|
||||
element.SetAttribute("ambientLightColorG", (int)GetAmbientLightColorGreen());
|
||||
element.SetAttribute("ambientLightColorB", (int)GetAmbientLightColorBlue());
|
||||
element.SetAttribute("camera3DNearPlaneDistance",
|
||||
GetCamera3DNearPlaneDistance());
|
||||
element.SetAttribute("camera3DFarPlaneDistance",
|
||||
GetCamera3DFarPlaneDistance());
|
||||
element.SetAttribute("camera3DFieldOfView", GetCamera3DFieldOfView());
|
||||
|
||||
SerializerElement& camerasElement = element.AddChild("cameras");
|
||||
camerasElement.ConsiderAsArrayOf("camera");
|
||||
@@ -71,27 +55,20 @@ void Layer::SerializeTo(SerializerElement& element) const {
|
||||
SerializerElement& effectsElement = element.AddChild("effects");
|
||||
effectsContainer.SerializeTo(effectsElement);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Unserialize the layer.
|
||||
*/
|
||||
void Layer::UnserializeFrom(const SerializerElement& element) {
|
||||
SetName(element.GetStringAttribute("name", "", "Name"));
|
||||
SetRenderingType(element.GetStringAttribute("renderingType", ""));
|
||||
SetVisibility(element.GetBoolAttribute("visibility", true, "Visibility"));
|
||||
SetLocked(element.GetBoolAttribute("isLocked", false));
|
||||
SetLightingLayer(element.GetBoolAttribute("isLightingLayer", false));
|
||||
SetFollowBaseLayerCamera(
|
||||
element.GetBoolAttribute("followBaseLayerCamera", false));
|
||||
SetAmbientLightColor(element.GetIntAttribute("ambientLightColorR", 200),
|
||||
element.GetIntAttribute("ambientLightColorG", 200),
|
||||
element.GetIntAttribute("ambientLightColorB", 200));
|
||||
SetCamera3DNearPlaneDistance(element.GetDoubleAttribute(
|
||||
"camera3DNearPlaneDistance", 0.1, "threeDNearPlaneDistance"));
|
||||
SetCamera3DFarPlaneDistance(element.GetDoubleAttribute(
|
||||
"camera3DFarPlaneDistance", 10000, "threeDFarPlaneDistance"));
|
||||
SetCamera3DFieldOfView(element.GetDoubleAttribute(
|
||||
"camera3DFieldOfView", 45, "threeDFieldOfView"));
|
||||
|
||||
cameras.clear();
|
||||
SerializerElement& camerasElement = element.GetChild("cameras");
|
||||
@@ -103,22 +80,24 @@ void Layer::UnserializeFrom(const SerializerElement& element) {
|
||||
camera.SetUseDefaultSize(
|
||||
cameraElement.GetBoolAttribute("defaultSize", true));
|
||||
camera.SetSize(cameraElement.GetDoubleAttribute("width"),
|
||||
cameraElement.GetDoubleAttribute("height"));
|
||||
cameraElement.GetDoubleAttribute("height"));
|
||||
camera.SetUseDefaultViewport(
|
||||
cameraElement.GetBoolAttribute("defaultViewport", true));
|
||||
camera.SetViewport(cameraElement.GetDoubleAttribute("viewportLeft"),
|
||||
cameraElement.GetDoubleAttribute("viewportTop"),
|
||||
cameraElement.GetDoubleAttribute("viewportRight"),
|
||||
cameraElement.GetDoubleAttribute("viewportBottom"));
|
||||
camera.SetViewport(
|
||||
cameraElement.GetDoubleAttribute("viewportLeft"),
|
||||
cameraElement.GetDoubleAttribute("viewportTop"),
|
||||
cameraElement.GetDoubleAttribute("viewportRight"),
|
||||
cameraElement.GetDoubleAttribute(
|
||||
"viewportBottom"));
|
||||
|
||||
cameras.push_back(camera);
|
||||
}
|
||||
|
||||
if (camerasElement.GetChildrenCount() > 50) {
|
||||
// Highly unlikely that we want as many cameras, as they were not even
|
||||
// exposed in the editor nor used in the game engine. Must be because of a
|
||||
// bug in the editor that duplicated cameras when cancelling changes on a
|
||||
// layer. Reset to one camera.
|
||||
// Highly unlikely that we want as many cameras, as they were not even exposed in
|
||||
// the editor nor used in the game engine. Must be because of a bug in the editor that
|
||||
// duplicated cameras when cancelling changes on a layer.
|
||||
// Reset to one camera.
|
||||
SetCameraCount(1);
|
||||
}
|
||||
|
||||
@@ -126,7 +105,9 @@ void Layer::UnserializeFrom(const SerializerElement& element) {
|
||||
effectsContainer.UnserializeFrom(effectsElement);
|
||||
}
|
||||
|
||||
gd::EffectsContainer& Layer::GetEffects() { return effectsContainer; }
|
||||
gd::EffectsContainer& Layer::GetEffects() {
|
||||
return effectsContainer;
|
||||
}
|
||||
|
||||
const gd::EffectsContainer& Layer::GetEffects() const {
|
||||
return effectsContainer;
|
||||
|
@@ -47,11 +47,6 @@ class GD_CORE_API Layer {
|
||||
*/
|
||||
const gd::String& GetName() const { return name; }
|
||||
|
||||
const gd::String& GetRenderingType() const { return renderingType; }
|
||||
void SetRenderingType(const gd::String& renderingType_) {
|
||||
renderingType = renderingType_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Change if layer is displayed or not
|
||||
*/
|
||||
@@ -63,17 +58,7 @@ class GD_CORE_API Layer {
|
||||
bool GetVisibility() const { return isVisible; }
|
||||
|
||||
/**
|
||||
* \brief Change if layer can be modified or not.
|
||||
*/
|
||||
void SetLocked(bool isLocked_) { isLocked = isLocked_; }
|
||||
|
||||
/**
|
||||
* \brief Return true if layer can't be modified.
|
||||
*/
|
||||
bool IsLocked() const { return isLocked; }
|
||||
|
||||
/**
|
||||
* \brief Set if the layer is a lighting layer or not.
|
||||
* \brief Set if the layer is a lightining layer or not.
|
||||
*/
|
||||
void SetLightingLayer(bool isLightingLayer_) {
|
||||
isLightingLayer = isLightingLayer_;
|
||||
@@ -96,25 +81,6 @@ class GD_CORE_API Layer {
|
||||
*/
|
||||
bool IsFollowingBaseLayerCamera() const { return followBaseLayerCamera; }
|
||||
|
||||
/** \name 3D
|
||||
*/
|
||||
///@{
|
||||
double GetCamera3DNearPlaneDistance() const {
|
||||
return camera3DNearPlaneDistance;
|
||||
}
|
||||
void SetCamera3DNearPlaneDistance(double distance) {
|
||||
camera3DNearPlaneDistance = distance;
|
||||
}
|
||||
double GetCamera3DFarPlaneDistance() const {
|
||||
return camera3DFarPlaneDistance;
|
||||
}
|
||||
void SetCamera3DFarPlaneDistance(double distance) {
|
||||
camera3DFarPlaneDistance = distance;
|
||||
}
|
||||
double GetCamera3DFieldOfView() const { return camera3DFieldOfView; }
|
||||
void SetCamera3DFieldOfView(double angle) { camera3DFieldOfView = angle; }
|
||||
///@}
|
||||
|
||||
/** \name Cameras
|
||||
*/
|
||||
///@{
|
||||
@@ -198,10 +164,12 @@ class GD_CORE_API Layer {
|
||||
const EffectsContainer& GetEffects() const;
|
||||
///@}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief Serialize layer.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Unserialize the layer.
|
||||
@@ -209,22 +177,16 @@ class GD_CORE_API Layer {
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
|
||||
private:
|
||||
gd::String name; ///< The name of the layer
|
||||
gd::String renderingType; ///< The rendering type: "" (empty), "2d", "3d" or
|
||||
///< "2d+3d".
|
||||
bool isVisible; ///< True if the layer is visible
|
||||
bool isLocked; ///< True if the layer is locked
|
||||
gd::String name; ///< The name of the layer
|
||||
bool isVisible; ///< True if the layer is visible
|
||||
bool isLightingLayer; ///< True if the layer is used to display lights and
|
||||
///< renders an ambient light.
|
||||
bool followBaseLayerCamera; ///< True if the layer automatically follows the
|
||||
///< base layer
|
||||
double camera3DNearPlaneDistance; ///< 3D camera frustum near plan distance
|
||||
double camera3DFarPlaneDistance; ///< 3D camera frustum far plan distance
|
||||
double camera3DFieldOfView; ///< 3D camera field of view (fov) in degrees
|
||||
unsigned int ambientLightColorR; ///< Ambient light color Red component
|
||||
unsigned int ambientLightColorG; ///< Ambient light color Green component
|
||||
unsigned int ambientLightColorB; ///< Ambient light color Blue component
|
||||
std::vector<gd::Camera> cameras; ///< The camera displayed by the layer
|
||||
unsigned int ambientLightColorR; ///< Ambient light color Red component
|
||||
unsigned int ambientLightColorG; ///< Ambient light color Green component
|
||||
unsigned int ambientLightColorB; ///< Ambient light color Blue component
|
||||
std::vector<gd::Camera> cameras; ///< The camera displayed by the layer
|
||||
gd::EffectsContainer effectsContainer; ///< The effects applied to the layer.
|
||||
|
||||
static gd::Camera badCamera;
|
||||
|
@@ -507,44 +507,6 @@ gd::String GD_CORE_API GetTypeOfObject(const gd::ObjectsContainer& project,
|
||||
return type;
|
||||
}
|
||||
|
||||
bool GD_CORE_API HasBehaviorInObjectOrGroup(const gd::ObjectsContainer &project,
|
||||
const gd::ObjectsContainer &layout,
|
||||
const gd::String &objectOrGroupName,
|
||||
const gd::String &behaviorName,
|
||||
bool searchInGroups) {
|
||||
// Search in objects
|
||||
if (layout.HasObjectNamed(objectOrGroupName)) {
|
||||
return layout.GetObject(objectOrGroupName).HasBehaviorNamed(behaviorName);
|
||||
}
|
||||
if (project.HasObjectNamed(objectOrGroupName)) {
|
||||
return project.GetObject(objectOrGroupName).HasBehaviorNamed(behaviorName);
|
||||
}
|
||||
|
||||
// Search in groups
|
||||
const gd::ObjectsContainer *container;
|
||||
if (layout.GetObjectGroups().Has(objectOrGroupName)) {
|
||||
container = &layout;
|
||||
} else if (project.GetObjectGroups().Has(objectOrGroupName)) {
|
||||
container = &project;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
const vector<gd::String> &groupsObjects =
|
||||
container->GetObjectGroups().Get(objectOrGroupName).GetAllObjectsNames();
|
||||
// Empty groups don't contain any behavior.
|
||||
if (groupsObjects.empty()) {
|
||||
return false;
|
||||
}
|
||||
// Check that all objects have the same type.
|
||||
for (auto &&object : groupsObjects) {
|
||||
if (!HasBehaviorInObjectOrGroup(project, layout, object, behaviorName,
|
||||
false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
gd::String GD_CORE_API GetTypeOfBehavior(const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
gd::String name,
|
||||
|
@@ -442,14 +442,7 @@ gd::String GD_CORE_API GetTypeOfObject(const ObjectsContainer& game,
|
||||
const ObjectsContainer& layout,
|
||||
gd::String objectName,
|
||||
bool searchInGroups = true);
|
||||
/**
|
||||
* \brief Check if an object or all object of a group has a behavior.
|
||||
*/
|
||||
bool GD_CORE_API HasBehaviorInObjectOrGroup(const gd::ObjectsContainer &project,
|
||||
const gd::ObjectsContainer &layout,
|
||||
const gd::String &objectOrGroupName,
|
||||
const gd::String &behaviorName,
|
||||
bool searchInGroups = true);
|
||||
|
||||
/**
|
||||
* \brief Get a type from a behavior name
|
||||
* @return Type of the behavior.
|
||||
|
@@ -5,17 +5,17 @@
|
||||
*/
|
||||
#ifndef GDCORE_OBJECT_H
|
||||
#define GDCORE_OBJECT_H
|
||||
#include "GDCore/Vector2.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/EffectsContainer.h"
|
||||
#include "GDCore/Project/ObjectConfiguration.h"
|
||||
#include "GDCore/Project/EffectsContainer.h"
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
#include "GDCore/Vector2.h"
|
||||
|
||||
namespace gd {
|
||||
class PropertyDescriptor;
|
||||
@@ -45,7 +45,7 @@ class GD_CORE_API Object {
|
||||
|
||||
/**
|
||||
* Create a new object with the name passed as argument.
|
||||
*
|
||||
*
|
||||
* Object takes the ownership of the configuration.
|
||||
*/
|
||||
Object(const gd::String& name,
|
||||
@@ -104,9 +104,7 @@ class GD_CORE_API Object {
|
||||
|
||||
/** \brief Change the asset store id of the object.
|
||||
*/
|
||||
void SetAssetStoreId(const gd::String& assetStoreId_) {
|
||||
assetStoreId = assetStoreId_;
|
||||
};
|
||||
void SetAssetStoreId(const gd::String& assetStoreId_) { assetStoreId = assetStoreId_; };
|
||||
|
||||
/** \brief Return the asset store id of the object.
|
||||
*/
|
||||
@@ -114,11 +112,15 @@ class GD_CORE_API Object {
|
||||
|
||||
/** \brief Change the type of the object.
|
||||
*/
|
||||
void SetType(const gd::String& type_) { configuration->SetType(type_); }
|
||||
void SetType(const gd::String& type_) {
|
||||
configuration->SetType(type_);
|
||||
}
|
||||
|
||||
/** \brief Return the type of the object.
|
||||
*/
|
||||
const gd::String& GetType() const { return configuration->GetType(); }
|
||||
const gd::String& GetType() const {
|
||||
return configuration->GetType();
|
||||
}
|
||||
|
||||
/** \brief Change the tags of the object.
|
||||
*/
|
||||
@@ -222,12 +224,12 @@ class GD_CORE_API Object {
|
||||
* effects.
|
||||
*/
|
||||
gd::EffectsContainer& GetEffects() { return effectsContainer; }
|
||||
///@}
|
||||
///@}
|
||||
|
||||
/** \name Serialization
|
||||
* Members functions related to serialization of the object
|
||||
*/
|
||||
///@{
|
||||
/** \name Serialization
|
||||
* Members functions related to serialization of the object
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Serialize the object.
|
||||
* \see DoSerializeTo
|
||||
@@ -242,9 +244,8 @@ class GD_CORE_API Object {
|
||||
///@}
|
||||
|
||||
protected:
|
||||
gd::String name; ///< The full name of the object
|
||||
gd::String assetStoreId; ///< The ID of the asset if the object comes from
|
||||
///< the store.
|
||||
gd::String name; ///< The full name of the object
|
||||
gd::String assetStoreId; ///< The ID of the asset if the object comes from the store.
|
||||
std::unique_ptr<gd::ObjectConfiguration> configuration;
|
||||
std::map<gd::String, std::unique_ptr<gd::Behavior>>
|
||||
behaviors; ///< Contains all behaviors and their properties for the
|
||||
@@ -259,7 +260,7 @@ class GD_CORE_API Object {
|
||||
/**
|
||||
* Initialize object using another object. Used by copy-ctor and assign-op.
|
||||
* Don't forget to update me if members were changed!
|
||||
*
|
||||
*
|
||||
* It's needed because there is no default copy for a map of unique_ptr like
|
||||
* behaviors and it must be a deep copy.
|
||||
*/
|
||||
@@ -282,4 +283,14 @@ struct ObjectHasName : public std::binary_function<std::unique_ptr<gd::Object>,
|
||||
|
||||
} // namespace gd
|
||||
|
||||
/**
|
||||
* An object list is a vector containing (smart) pointers to objects.
|
||||
*/
|
||||
using ObjList = std::vector<std::unique_ptr<gd::Object>>;
|
||||
|
||||
/**
|
||||
* Objects are usually managed thanks to (smart) pointers.
|
||||
*/
|
||||
using ObjSPtr = std::unique_ptr<gd::Object>;
|
||||
|
||||
#endif // GDCORE_OBJECT_H
|
||||
|
@@ -5,10 +5,8 @@
|
||||
*/
|
||||
|
||||
#include "ObjectGroup.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
@@ -43,9 +41,8 @@ void ObjectGroup::SerializeTo(SerializerElement& element) const {
|
||||
|
||||
SerializerElement& objectsElement = element.AddChild("objects");
|
||||
objectsElement.ConsiderAsArrayOf("object");
|
||||
for (auto& name : GetAllObjectsNames()) {
|
||||
for (auto& name : GetAllObjectsNames())
|
||||
objectsElement.AddChild("object").SetAttribute("name", name);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectGroup::UnserializeFrom(const SerializerElement& element) {
|
||||
|
@@ -8,9 +8,7 @@
|
||||
#define GDCORE_OBJECTGROUP_H
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
|
@@ -4,113 +4,79 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "ObjectGroupsContainer.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "GDCore/Project/ObjectGroupsContainer.h"
|
||||
#include "GDCore/Project/ObjectGroup.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
|
||||
namespace gd {
|
||||
gd::ObjectGroup ObjectGroupsContainer::badGroup;
|
||||
|
||||
ObjectGroupsContainer::ObjectGroupsContainer() {}
|
||||
|
||||
ObjectGroupsContainer::ObjectGroupsContainer(
|
||||
const ObjectGroupsContainer& other) {
|
||||
Init(other);
|
||||
}
|
||||
|
||||
ObjectGroupsContainer& ObjectGroupsContainer::operator=(
|
||||
const ObjectGroupsContainer& other) {
|
||||
if (this != &other) Init(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ObjectGroupsContainer::Init(const ObjectGroupsContainer& other) {
|
||||
objectGroups.clear();
|
||||
for (auto& it : other.objectGroups) {
|
||||
objectGroups.push_back(gd::make_unique<gd::ObjectGroup>(*it));
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectGroupsContainer::SerializeTo(SerializerElement& element) const {
|
||||
element.ConsiderAsArrayOf("group");
|
||||
for (std::size_t i = 0; i < objectGroups.size(); ++i) {
|
||||
objectGroups[i]->SerializeTo(element.AddChild("group"));
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectGroupsContainer::UnserializeFrom(const SerializerElement& element) {
|
||||
objectGroups.clear();
|
||||
element.ConsiderAsArrayOf("group", "Groupe");
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& groupElement = element.GetChild(i);
|
||||
gd::ObjectGroup& objectGroup =
|
||||
InsertNew(element.GetStringAttribute("name", "", "nom"), -1);
|
||||
objectGroup.UnserializeFrom(groupElement);
|
||||
}
|
||||
}
|
||||
ObjectGroup ObjectGroupsContainer::badGroup;
|
||||
|
||||
bool ObjectGroupsContainer::Has(const gd::String& name) const {
|
||||
auto i = std::find_if(objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&name](const std::unique_ptr<gd::ObjectGroup>& group) {
|
||||
return group->GetName() == name;
|
||||
});
|
||||
auto i = std::find_if(
|
||||
objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&name](const ObjectGroup& group) { return group.GetName() == name; });
|
||||
return (i != objectGroups.end());
|
||||
}
|
||||
|
||||
ObjectGroup& ObjectGroupsContainer::Get(std::size_t index) {
|
||||
if (index < objectGroups.size()) return *objectGroups[index];
|
||||
if (index < objectGroups.size()) return objectGroups[index];
|
||||
|
||||
return badGroup;
|
||||
}
|
||||
|
||||
const ObjectGroup& ObjectGroupsContainer::Get(std::size_t index) const {
|
||||
if (index < objectGroups.size()) return *objectGroups[index];
|
||||
if (index < objectGroups.size()) return objectGroups[index];
|
||||
|
||||
return badGroup;
|
||||
}
|
||||
|
||||
ObjectGroup& ObjectGroupsContainer::Get(const gd::String& name) {
|
||||
auto i = std::find_if(objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&name](const std::unique_ptr<gd::ObjectGroup>& group) {
|
||||
return group->GetName() == name;
|
||||
});
|
||||
if (i != objectGroups.end()) return **i;
|
||||
auto i = std::find_if(
|
||||
objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&name](const ObjectGroup& group) { return group.GetName() == name; });
|
||||
if (i != objectGroups.end()) return *i;
|
||||
|
||||
return badGroup;
|
||||
}
|
||||
|
||||
const ObjectGroup& ObjectGroupsContainer::Get(const gd::String& name) const {
|
||||
auto i = std::find_if(objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&name](const std::unique_ptr<gd::ObjectGroup>& group) {
|
||||
return group->GetName() == name;
|
||||
});
|
||||
if (i != objectGroups.end()) return **i;
|
||||
auto i = std::find_if(
|
||||
objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&name](const ObjectGroup& group) { return group.GetName() == name; });
|
||||
if (i != objectGroups.end()) return *i;
|
||||
|
||||
return badGroup;
|
||||
}
|
||||
|
||||
ObjectGroup& ObjectGroupsContainer::Insert(const gd::ObjectGroup& group,
|
||||
std::size_t position) {
|
||||
if (position < objectGroups.size()) {
|
||||
objectGroups.insert(objectGroups.begin() + position, group);
|
||||
return objectGroups[position];
|
||||
} else {
|
||||
objectGroups.push_back(group);
|
||||
return objectGroups.back();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void ObjectGroupsContainer::Remove(const gd::String& name) {
|
||||
objectGroups.erase(
|
||||
std::remove_if(objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&name](const std::unique_ptr<gd::ObjectGroup>& group) {
|
||||
return group->GetName() == name;
|
||||
}),
|
||||
objectGroups.end());
|
||||
objectGroups.erase(std::remove_if(objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&name](const ObjectGroup& group) {
|
||||
return group.GetName() == name;
|
||||
}),
|
||||
objectGroups.end());
|
||||
}
|
||||
|
||||
std::size_t ObjectGroupsContainer::GetPosition(const gd::String& name) const {
|
||||
for (std::size_t i = 0; i < objectGroups.size(); ++i) {
|
||||
if (objectGroups[i]->GetName() == name) return i;
|
||||
if (objectGroups[i].GetName() == name) return i;
|
||||
}
|
||||
|
||||
return gd::String::npos;
|
||||
@@ -118,36 +84,21 @@ std::size_t ObjectGroupsContainer::GetPosition(const gd::String& name) const {
|
||||
|
||||
ObjectGroup& ObjectGroupsContainer::InsertNew(const gd::String& name,
|
||||
std::size_t position) {
|
||||
gd::ObjectGroup& newlyInsertedGroup = *(*(objectGroups.insert(
|
||||
position < objectGroups.size() ? objectGroups.begin() + position
|
||||
: objectGroups.end(),
|
||||
gd::make_unique<gd::ObjectGroup>())));
|
||||
newlyInsertedGroup.SetName(name);
|
||||
return newlyInsertedGroup;
|
||||
}
|
||||
|
||||
ObjectGroup& ObjectGroupsContainer::Insert(const gd::ObjectGroup& group,
|
||||
std::size_t position) {
|
||||
gd::ObjectGroup& newlyInsertedGroup = *(*(objectGroups.insert(
|
||||
position < objectGroups.size() ? objectGroups.begin() + position
|
||||
: objectGroups.end(),
|
||||
gd::make_unique<gd::ObjectGroup>(group))));
|
||||
return newlyInsertedGroup;
|
||||
ObjectGroup newGroup;
|
||||
newGroup.SetName(name);
|
||||
return Insert(newGroup, position);
|
||||
}
|
||||
|
||||
bool ObjectGroupsContainer::Rename(const gd::String& oldName,
|
||||
const gd::String& newName) {
|
||||
if (Has(newName)) return false;
|
||||
|
||||
auto i =
|
||||
std::find_if(objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&oldName](const std::unique_ptr<gd::ObjectGroup>& group) {
|
||||
return group->GetName() == oldName;
|
||||
});
|
||||
if (i != objectGroups.end()) {
|
||||
(*i)->SetName(newName);
|
||||
}
|
||||
auto i = std::find_if(objectGroups.begin(),
|
||||
objectGroups.end(),
|
||||
[&oldName](const ObjectGroup& group) {
|
||||
return group.GetName() == oldName;
|
||||
});
|
||||
if (i != objectGroups.end()) i->SetName(newName);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -156,10 +107,30 @@ void ObjectGroupsContainer::Move(std::size_t oldIndex, std::size_t newIndex) {
|
||||
if (oldIndex >= objectGroups.size() || newIndex >= objectGroups.size())
|
||||
return;
|
||||
|
||||
std::unique_ptr<gd::ObjectGroup> objectGroup =
|
||||
std::move(objectGroups[oldIndex]);
|
||||
auto group = objectGroups[oldIndex];
|
||||
objectGroups.erase(objectGroups.begin() + oldIndex);
|
||||
objectGroups.insert(objectGroups.begin() + newIndex, std::move(objectGroup));
|
||||
Insert(group, newIndex);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ObjectGroupsContainer::SerializeTo(SerializerElement& element) const {
|
||||
element.ConsiderAsArrayOf("group");
|
||||
for (auto& group : objectGroups) {
|
||||
SerializerElement& groupElement = element.AddChild("group");
|
||||
group.SerializeTo(groupElement);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectGroupsContainer::UnserializeFrom(const SerializerElement& element) {
|
||||
objectGroups.clear();
|
||||
element.ConsiderAsArrayOf("group", "Groupe");
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
|
||||
SerializerElement& groupElement = element.GetChild(i);
|
||||
gd::ObjectGroup objectGroup;
|
||||
|
||||
objectGroup.UnserializeFrom(groupElement);
|
||||
objectGroups.push_back(objectGroup);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -6,10 +6,8 @@
|
||||
|
||||
#ifndef GDCORE_OBJECTGROUPSCONTAINER_H
|
||||
#define GDCORE_OBJECTGROUPSCONTAINER_H
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <algorithm>
|
||||
#include "GDCore/Project/ObjectGroup.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
@@ -28,10 +26,8 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API ObjectGroupsContainer {
|
||||
public:
|
||||
ObjectGroupsContainer();
|
||||
ObjectGroupsContainer(const ObjectGroupsContainer&);
|
||||
ObjectGroupsContainer(){};
|
||||
virtual ~ObjectGroupsContainer(){};
|
||||
ObjectGroupsContainer& operator=(const ObjectGroupsContainer& rhs);
|
||||
|
||||
/**
|
||||
* \brief Return true if the specified group is in the container
|
||||
@@ -175,14 +171,8 @@ class GD_CORE_API ObjectGroupsContainer {
|
||||
const ObjectGroup& at(size_t index) const { return Get(index); };
|
||||
///@}
|
||||
|
||||
/**
|
||||
* Initialize from another object groups container. Used by copy-ctor and
|
||||
* assign-op. Don't forget to update me if members were changed!
|
||||
*/
|
||||
void Init(const gd::ObjectGroupsContainer& other);
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<gd::ObjectGroup>> objectGroups;
|
||||
std::vector<ObjectGroup> objectGroups;
|
||||
static ObjectGroup badGroup;
|
||||
};
|
||||
|
||||
|
@@ -4,9 +4,7 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
@@ -18,12 +16,14 @@ ObjectsContainer::ObjectsContainer() {}
|
||||
|
||||
ObjectsContainer::~ObjectsContainer() {}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void ObjectsContainer::SerializeObjectsTo(SerializerElement& element) const {
|
||||
element.ConsiderAsArrayOf("object");
|
||||
for (std::size_t j = 0; j < initialObjects.size(); j++) {
|
||||
initialObjects[j]->SerializeTo(element.AddChild("object"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ObjectsContainer::UnserializeObjectsFrom(
|
||||
gd::Project& project, const SerializerElement& element) {
|
||||
@@ -75,6 +75,7 @@ std::size_t ObjectsContainer::GetObjectPosition(const gd::String& name) const {
|
||||
std::size_t ObjectsContainer::GetObjectsCount() const {
|
||||
return initialObjects.size();
|
||||
}
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::Object& ObjectsContainer::InsertNewObject(const gd::Project& project,
|
||||
const gd::String& objectType,
|
||||
const gd::String& name,
|
||||
@@ -86,6 +87,7 @@ gd::Object& ObjectsContainer::InsertNewObject(const gd::Project& project,
|
||||
|
||||
return newlyCreatedObject;
|
||||
}
|
||||
#endif
|
||||
|
||||
gd::Object& ObjectsContainer::InsertObject(const gd::Object& object,
|
||||
std::size_t position) {
|
||||
@@ -117,7 +119,7 @@ void ObjectsContainer::MoveObject(std::size_t oldIndex, std::size_t newIndex) {
|
||||
}
|
||||
|
||||
void ObjectsContainer::RemoveObject(const gd::String& name) {
|
||||
std::vector<std::unique_ptr<gd::Object>>::iterator objectIt =
|
||||
std::vector<std::unique_ptr<gd::Object> >::iterator objectIt =
|
||||
find_if(initialObjects.begin(),
|
||||
initialObjects.end(),
|
||||
bind2nd(ObjectHasName(), name));
|
||||
@@ -130,7 +132,7 @@ void ObjectsContainer::MoveObjectToAnotherContainer(
|
||||
const gd::String& name,
|
||||
gd::ObjectsContainer& newContainer,
|
||||
std::size_t newPosition) {
|
||||
std::vector<std::unique_ptr<gd::Object>>::iterator objectIt =
|
||||
std::vector<std::unique_ptr<gd::Object> >::iterator objectIt =
|
||||
find_if(initialObjects.begin(),
|
||||
initialObjects.end(),
|
||||
bind2nd(ObjectHasName(), name));
|
||||
|
@@ -81,23 +81,24 @@ Project::~Project() {}
|
||||
void Project::ResetProjectUuid() { projectUuid = UUID::MakeUuid4(); }
|
||||
|
||||
std::unique_ptr<gd::Object> Project::CreateObject(
|
||||
const gd::String& type, const gd::String& name) const {
|
||||
return gd::make_unique<Object>(name, type, CreateObjectConfiguration(type));
|
||||
const gd::String& type,
|
||||
const gd::String& name) const {
|
||||
return gd::make_unique<Object>(name, type, CreateObjectConfiguration(type));
|
||||
}
|
||||
|
||||
std::unique_ptr<gd::ObjectConfiguration> Project::CreateObjectConfiguration(
|
||||
const gd::String& type) const {
|
||||
const gd::String& type) const {
|
||||
if (Project::HasEventsBasedObject(type)) {
|
||||
return gd::make_unique<CustomObjectConfiguration>(*this, type);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// Create a base object if the type can't be found in the platform.
|
||||
return currentPlatform->CreateObjectConfiguration(type);
|
||||
}
|
||||
}
|
||||
|
||||
bool Project::HasEventsBasedObject(const gd::String& type) const {
|
||||
const auto separatorIndex =
|
||||
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
if (separatorIndex == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
@@ -105,67 +106,59 @@ bool Project::HasEventsBasedObject(const gd::String& type) const {
|
||||
if (!Project::HasEventsFunctionsExtensionNamed(extensionName)) {
|
||||
return false;
|
||||
}
|
||||
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
gd::String objectTypeName = type.substr(separatorIndex + 2);
|
||||
return extension.GetEventsBasedObjects().Has(objectTypeName);
|
||||
}
|
||||
|
||||
gd::EventsBasedObject& Project::GetEventsBasedObject(const gd::String& type) {
|
||||
const auto separatorIndex =
|
||||
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
gd::String extensionName = type.substr(0, separatorIndex);
|
||||
gd::String objectTypeName = type.substr(separatorIndex + 2);
|
||||
|
||||
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
return extension.GetEventsBasedObjects().Get(objectTypeName);
|
||||
}
|
||||
|
||||
const gd::EventsBasedObject& Project::GetEventsBasedObject(
|
||||
const gd::String& type) const {
|
||||
const auto separatorIndex =
|
||||
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
const gd::EventsBasedObject& Project::GetEventsBasedObject(const gd::String& type) const {
|
||||
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
gd::String extensionName = type.substr(0, separatorIndex);
|
||||
gd::String objectTypeName = type.substr(separatorIndex + 2);
|
||||
|
||||
const auto& extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
const auto &extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
return extension.GetEventsBasedObjects().Get(objectTypeName);
|
||||
}
|
||||
|
||||
bool Project::HasEventsBasedBehavior(const gd::String& type) const {
|
||||
const auto separatorIndex =
|
||||
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
if (separatorIndex == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
gd::String extensionName = type.substr(0, separatorIndex);
|
||||
if (!Project::HasEventsFunctionsExtensionNamed(extensionName)) {
|
||||
return false;
|
||||
}
|
||||
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
|
||||
return extension.GetEventsBasedBehaviors().Has(behaviorTypeName);
|
||||
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
if (separatorIndex == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
gd::String extensionName = type.substr(0, separatorIndex);
|
||||
if (!Project::HasEventsFunctionsExtensionNamed(extensionName)) {
|
||||
return false;
|
||||
}
|
||||
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
|
||||
return extension.GetEventsBasedBehaviors().Has(behaviorTypeName);
|
||||
}
|
||||
|
||||
gd::EventsBasedBehavior& Project::GetEventsBasedBehavior(
|
||||
const gd::String& type) {
|
||||
const auto separatorIndex =
|
||||
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
gd::String extensionName = type.substr(0, separatorIndex);
|
||||
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
|
||||
gd::EventsBasedBehavior& Project::GetEventsBasedBehavior(const gd::String& type) {
|
||||
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
gd::String extensionName = type.substr(0, separatorIndex);
|
||||
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
|
||||
|
||||
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
return extension.GetEventsBasedBehaviors().Get(behaviorTypeName);
|
||||
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
return extension.GetEventsBasedBehaviors().Get(behaviorTypeName);
|
||||
}
|
||||
|
||||
const gd::EventsBasedBehavior& Project::GetEventsBasedBehavior(
|
||||
const gd::String& type) const {
|
||||
const auto separatorIndex =
|
||||
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
gd::String extensionName = type.substr(0, separatorIndex);
|
||||
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
|
||||
const gd::EventsBasedBehavior& Project::GetEventsBasedBehavior(const gd::String& type) const {
|
||||
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
gd::String extensionName = type.substr(0, separatorIndex);
|
||||
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
|
||||
|
||||
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
return extension.GetEventsBasedBehaviors().Get(behaviorTypeName);
|
||||
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
|
||||
return extension.GetEventsBasedBehaviors().Get(behaviorTypeName);
|
||||
}
|
||||
|
||||
std::shared_ptr<gd::BaseEvent> Project::CreateEvent(
|
||||
@@ -385,7 +378,7 @@ void Project::MoveExternalLayout(std::size_t oldIndex, std::size_t newIndex) {
|
||||
};
|
||||
|
||||
void Project::MoveEventsFunctionsExtension(std::size_t oldIndex,
|
||||
std::size_t newIndex) {
|
||||
std::size_t newIndex) {
|
||||
if (oldIndex >= eventsFunctionsExtensions.size() ||
|
||||
newIndex >= eventsFunctionsExtensions.size())
|
||||
return;
|
||||
@@ -1012,7 +1005,7 @@ void Project::ExposeResources(gd::ArbitraryResourceWorker& worker) {
|
||||
// Add layouts resources
|
||||
for (std::size_t s = 0; s < GetLayoutsCount(); s++) {
|
||||
for (std::size_t j = 0; j < GetLayout(s).GetObjectsCount();
|
||||
++j) { // Add objects resources
|
||||
++j) { // Add objects resources
|
||||
GetLayout(s).GetObject(j).GetConfiguration().ExposeResources(worker);
|
||||
}
|
||||
|
||||
|
@@ -91,8 +91,6 @@ std::shared_ptr<Resource> ResourcesManager::CreateResource(
|
||||
return std::make_shared<TilesetResource>();
|
||||
else if (kind == "bitmapFont")
|
||||
return std::make_shared<BitmapFontResource>();
|
||||
else if (kind == "model3D")
|
||||
return std::make_shared<Model3DResource>();
|
||||
|
||||
std::cout << "Bad resource created (type: " << kind << ")" << std::endl;
|
||||
return std::make_shared<Resource>();
|
||||
@@ -738,20 +736,6 @@ void BitmapFontResource::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("file", GetFile());
|
||||
}
|
||||
|
||||
void Model3DResource::SetFile(const gd::String& newFile) {
|
||||
file = NormalizePathSeparator(newFile);
|
||||
}
|
||||
|
||||
void Model3DResource::UnserializeFrom(const SerializerElement& element) {
|
||||
SetUserAdded(element.GetBoolAttribute("userAdded"));
|
||||
SetFile(element.GetStringAttribute("file"));
|
||||
}
|
||||
|
||||
void Model3DResource::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("userAdded", IsUserAdded());
|
||||
element.SetAttribute("file", GetFile());
|
||||
}
|
||||
|
||||
ResourceFolder::ResourceFolder(const ResourceFolder& other) { Init(other); }
|
||||
|
||||
ResourceFolder& ResourceFolder::operator=(const ResourceFolder& other) {
|
||||
|
@@ -142,7 +142,7 @@ class GD_CORE_API Resource {
|
||||
virtual void SerializeTo(SerializerElement& element) const {};
|
||||
|
||||
/**
|
||||
* \brief Unserialize the object.
|
||||
* \brief Unserialize the objectt.
|
||||
*/
|
||||
virtual void UnserializeFrom(const SerializerElement& element){};
|
||||
|
||||
@@ -195,7 +195,7 @@ class GD_CORE_API ImageResource : public Resource {
|
||||
void SerializeTo(SerializerElement& element) const override;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the object.
|
||||
* \brief Unserialize the objectt.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element) override;
|
||||
|
||||
@@ -481,32 +481,6 @@ class GD_CORE_API BitmapFontResource : public Resource {
|
||||
gd::String file;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Describe a 3D model file used by a project.
|
||||
*
|
||||
* \see Resource
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API Model3DResource : public Resource {
|
||||
public:
|
||||
Model3DResource() : Resource() { SetKind("model3D"); };
|
||||
virtual ~Model3DResource(){};
|
||||
virtual Model3DResource* Clone() const override {
|
||||
return new Model3DResource(*this);
|
||||
}
|
||||
|
||||
virtual const gd::String& GetFile() const override { return file; };
|
||||
virtual void SetFile(const gd::String& newFile) override;
|
||||
|
||||
virtual bool UseFile() const override { return true; }
|
||||
void SerializeTo(SerializerElement& element) const override;
|
||||
|
||||
void UnserializeFrom(const SerializerElement& element) override;
|
||||
|
||||
private:
|
||||
gd::String file;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Inventory all resources used by a project
|
||||
*
|
||||
@@ -663,7 +637,7 @@ class GD_CORE_API ResourcesManager {
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the object.
|
||||
* \brief Unserialize the objectt.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
|
||||
@@ -740,7 +714,7 @@ class GD_CORE_API ResourceFolder {
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the object.
|
||||
* \brief Unserialize the objectt.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element,
|
||||
gd::ResourcesManager& parentManager);
|
||||
|
@@ -2280,7 +2280,7 @@ public:
|
||||
//!@name Handling parse errors
|
||||
//!@{
|
||||
|
||||
//! Whether a parse error has occurred in the last parsing.
|
||||
//! Whether a parse error has occured in the last parsing.
|
||||
bool HasParseError() const { return parseResult_.IsError(); }
|
||||
|
||||
//! Get the \ref ParseErrorCode of last parsing.
|
||||
|
@@ -527,7 +527,7 @@ public:
|
||||
return Parse<kParseDefaultFlags>(is, handler);
|
||||
}
|
||||
|
||||
//! Whether a parse error has occurred in the last parsing.
|
||||
//! Whether a parse error has occured in the last parsing.
|
||||
bool HasParseError() const { return parseResult_.IsError(); }
|
||||
|
||||
//! Get the \ref ParseErrorCode of last parsing.
|
||||
|
@@ -584,32 +584,32 @@ public:
|
||||
String substr( size_type start = 0, size_type length = npos ) const;
|
||||
|
||||
/**
|
||||
* \return the position of the first occurrence of **search** starting from **pos**.
|
||||
* \return the position of the first occurence of **search** starting from **pos**.
|
||||
*/
|
||||
size_type find( const String &search, size_type pos = 0 ) const;
|
||||
|
||||
/**
|
||||
* \return the position of the first occurrence of **search** starting from **pos**.
|
||||
* \return the position of the first occurence of **search** starting from **pos**.
|
||||
*/
|
||||
size_type find( const char *search, size_type pos = 0 ) const;
|
||||
|
||||
/**
|
||||
* \return the position of the first occurrence of **search** starting from **pos**.
|
||||
* \return the position of the first occurence of **search** starting from **pos**.
|
||||
*/
|
||||
size_type find( const value_type search, size_type pos = 0 ) const;
|
||||
|
||||
/**
|
||||
* \return the position of the last occurrence of **search** starting before **pos**.
|
||||
* \return the position of the last occurence of **search** starting before **pos**.
|
||||
*/
|
||||
size_type rfind( const String &search, size_type pos = npos ) const;
|
||||
|
||||
/**
|
||||
* \return the position of the last occurrence of **search** starting before **pos**.
|
||||
* \return the position of the last occurence of **search** starting before **pos**.
|
||||
*/
|
||||
size_type rfind( const char *search, size_type pos = npos ) const;
|
||||
|
||||
/**
|
||||
* \return the position of the last occurrence of **search** starting before **pos**.
|
||||
* \return the position of the last occurence of **search** starting before **pos**.
|
||||
*/
|
||||
size_type rfind( const value_type &search, size_type pos = npos ) const;
|
||||
|
||||
@@ -658,7 +658,7 @@ public:
|
||||
|
||||
/**
|
||||
* \brief Do a case-insensitive search
|
||||
* \return the position of the first occurrence of **search** starting from **pos**.
|
||||
* \return the position of the first occurence of **search** starting from **pos**.
|
||||
*
|
||||
* \note This method isn't very efficient as it is linear on the string size times the
|
||||
* search string size
|
||||
|
10
Core/GDCore/TinyXml/tinyxml.h
vendored
10
Core/GDCore/TinyXml/tinyxml.h
vendored
@@ -577,7 +577,7 @@ public:
|
||||
#endif
|
||||
|
||||
/** Add a new node related to this. Adds a child past the LastChild.
|
||||
Returns a pointer to the new object or NULL if an error occurred.
|
||||
Returns a pointer to the new object or NULL if an error occured.
|
||||
*/
|
||||
TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
|
||||
|
||||
@@ -594,17 +594,17 @@ public:
|
||||
TiXmlNode* LinkEndChild( TiXmlNode* addThis );
|
||||
|
||||
/** Add a new node related to this. Adds a child before the specified child.
|
||||
Returns a pointer to the new object or NULL if an error occurred.
|
||||
Returns a pointer to the new object or NULL if an error occured.
|
||||
*/
|
||||
TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
|
||||
|
||||
/** Add a new node related to this. Adds a child after the specified child.
|
||||
Returns a pointer to the new object or NULL if an error occurred.
|
||||
Returns a pointer to the new object or NULL if an error occured.
|
||||
*/
|
||||
TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis );
|
||||
|
||||
/** Replace a child of this node.
|
||||
Returns a pointer to the new object or NULL if an error occurred.
|
||||
Returns a pointer to the new object or NULL if an error occured.
|
||||
*/
|
||||
TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
|
||||
|
||||
@@ -1471,7 +1471,7 @@ public:
|
||||
@sa SetTabSize, Row, Column
|
||||
*/
|
||||
int ErrorRow() const { return errorLocation.row+1; }
|
||||
int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occurred. See ErrorRow()
|
||||
int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow()
|
||||
|
||||
/** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol())
|
||||
to report the correct values for row and column. It does not change the output
|
||||
|
@@ -99,7 +99,7 @@ Everything in GDevelop.js is meant to create a "bridge" allowing us to run and u
|
||||
|
||||
### I want all the gory details about GDevelop.js 🧐
|
||||
|
||||
All the required C++ files are imported into this huge list: <https://github.com/4ian/GDevelop/blob/master/GDevelop.js/Bindings/Wrapper.cpp#L1-L79>. C++ compilation is done with a "build system" called CMake, which is using [this file](https://github.com/4ian/GDevelop/blob/master/GDevelop.js/CMakeLists.txt#L82-L101) to see what to compile.
|
||||
All the required C++ files are imported into this huge list: https://github.com/4ian/GDevelop/blob/master/GDevelop.js/Bindings/Wrapper.cpp#L1-L79. C++ compilation is done with a "build system" called CMake, which is using [this file](https://github.com/4ian/GDevelop/blob/master/GDevelop.js/CMakeLists.txt#L82-L101) to see what to compile.
|
||||
|
||||
> In an ideal world, there would be something to do this automatically, so the GDevelop.js folder would not even exist 😉
|
||||
> If you're interested and want to know more about GDevelop.js bridging between C++ and JavaScript, look at [this talk from GDevelop original author](https://www.youtube.com/watch?v=6La7jSCnYyk).
|
||||
|
@@ -6,7 +6,7 @@ GDevelop Core is a portable C++ library, compiled to be used in JavaScript in th
|
||||
|
||||
## 1) Getting started 🤓
|
||||
|
||||
First, take a look at the _[README.md](../README.md)_ at the root of the repository and the [developer documentation](https://docs.gdevelop.io/).
|
||||
First, take a look at the _Readme.md_ at the root of the repository and the [developer documentation](https://docs.gdevelop.io/).
|
||||
|
||||
## 2) How to contribute 😎
|
||||
|
||||
@@ -21,5 +21,5 @@ or any pull request so as to add a nice feature, do not hesitate to get in touch
|
||||
|
||||
## License
|
||||
|
||||
GDevelop Core is distributed under the MIT license: see [LICENSE.md](LICENSE.md) for
|
||||
GDevelop Core is distributed under the MIT license: see license.txt for
|
||||
more information.
|
||||
|
@@ -12,16 +12,16 @@ 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 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.
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
|
||||
External libraries used by GDevelop Core
|
@@ -124,14 +124,6 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
|
||||
.AddParameter("expression", _("Number parameter"))
|
||||
.SetRequiresBaseObjectCapability("effect")
|
||||
.SetFunctionName("getSomethingRequiringEffectCapability");
|
||||
baseObject
|
||||
.AddExpression("GetFromBaseExpression",
|
||||
"This works on any object.",
|
||||
"",
|
||||
"",
|
||||
"")
|
||||
.AddParameter("object", _("Object"), "")
|
||||
.SetFunctionName("getFromBaseExpression");
|
||||
|
||||
// Create an extension with various stuff inside.
|
||||
std::shared_ptr<gd::PlatformExtension> extension =
|
||||
|
@@ -197,14 +197,14 @@ TEST_CASE("ExpressionNodeLocationFinder", "[common][events]") {
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Numbers and texts mismatches") {
|
||||
SECTION("Numbers and texts mismatchs") {
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::NumberNode>(parser, "12+\"hello\"", 0) == true);
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::NumberNode>(parser, "12+\"hello\"", 1) == true);
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::OperatorNode>(parser, "12+\"hello\"", 2) == true);
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::TextNode>(parser, "12+\"hello\"", 3) == true);
|
||||
}
|
||||
|
||||
SECTION("Numbers and texts mismatches (parent node)") {
|
||||
SECTION("Numbers and texts mismatchs (parent node)") {
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::OperatorNode>(parser, "12+\"hello\"", 0) == true);
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::OperatorNode>(parser, "12+\"hello\"", 1) == true);
|
||||
REQUIRE(CheckNoParentNodeAtLocation(parser, "12+\"hello\"", 2) == true);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -132,11 +132,11 @@ TEST_CASE("ExpressionParser2NodePrinter", "[common][events]") {
|
||||
testPrinter("number", "123 !!! 456", "123 ! !! 456");
|
||||
}
|
||||
|
||||
SECTION("Numbers and texts mismatches") {
|
||||
SECTION("Numbers and texts mismatchs") {
|
||||
testPrinter("number", "123 + \"hello world\"");
|
||||
testPrinter("string", "\"hello world\" + 123");
|
||||
}
|
||||
SECTION("Numbers and texts mismatches with parenthesis") {
|
||||
SECTION("Numbers and texts mismatchs with parenthesis") {
|
||||
testPrinter("number", "((123)) + (\"hello world\")");
|
||||
testPrinter("string", "((\"hello world\") + (123))");
|
||||
}
|
||||
|
@@ -56,12 +56,6 @@ GetEventFirstActionFirstParameterString(const gd::BaseEvent &event) {
|
||||
return actions.Get(0).GetParameter(0).GetPlainString();
|
||||
}
|
||||
|
||||
bool
|
||||
AreActionsEmpty(const gd::BaseEvent &event) {
|
||||
auto &actions = EnsureStandardEvent(event).GetActions();
|
||||
return actions.IsEmpty();
|
||||
}
|
||||
|
||||
const gd::String &GetEventFirstConditionType(const gd::BaseEvent &event) {
|
||||
auto &conditions = EnsureStandardEvent(event).GetConditions();
|
||||
REQUIRE(conditions.IsEmpty() == false);
|
||||
@@ -84,8 +78,6 @@ enum TestEvent {
|
||||
FreeActionWithOperator,
|
||||
FreeFunctionWithObjects,
|
||||
FreeFunctionWithObjectExpression,
|
||||
FreeFunctionWithGroup,
|
||||
FreeFunctionWithObjectExpressionOnGroup,
|
||||
|
||||
BehaviorAction,
|
||||
BehaviorPropertyAction,
|
||||
@@ -115,18 +107,11 @@ enum TestEvent {
|
||||
ObjectActionWithOperator,
|
||||
};
|
||||
|
||||
const std::vector<const gd::EventsList *> GetEventsListsAssociatedToScene(gd::Project &project) {
|
||||
const std::vector<const gd::EventsList *> GetEventsLists(gd::Project &project) {
|
||||
std::vector<const gd::EventsList *> eventLists;
|
||||
auto &scene = project.GetLayout("Scene").GetEvents();
|
||||
auto &externalEvents =
|
||||
project.GetExternalEvents("ExternalEvents").GetEvents();
|
||||
eventLists.push_back(&scene);
|
||||
eventLists.push_back(&externalEvents);
|
||||
return eventLists;
|
||||
}
|
||||
|
||||
const std::vector<const gd::EventsList *> GetEventsListsNotAssociatedToScene(gd::Project &project) {
|
||||
std::vector<const gd::EventsList *> eventLists;
|
||||
auto &eventsExtension = project.GetEventsFunctionsExtension("MyEventsExtension");
|
||||
auto &objectFunctionEvents =
|
||||
eventsExtension
|
||||
@@ -143,24 +128,14 @@ const std::vector<const gd::EventsList *> GetEventsListsNotAssociatedToScene(gd:
|
||||
.GetEvents();
|
||||
auto &freeFunctionEvents =
|
||||
eventsExtension.GetEventsFunction("MyOtherEventsFunction").GetEvents();
|
||||
eventLists.push_back(&scene);
|
||||
eventLists.push_back(&externalEvents);
|
||||
eventLists.push_back(&objectFunctionEvents);
|
||||
eventLists.push_back(&behaviorFunctionEvents);
|
||||
eventLists.push_back(&freeFunctionEvents);
|
||||
return eventLists;
|
||||
}
|
||||
|
||||
const std::vector<const gd::EventsList *> GetEventsLists(gd::Project &project) {
|
||||
std::vector<const gd::EventsList *> eventLists;
|
||||
|
||||
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
|
||||
eventLists.push_back(eventsList);
|
||||
}
|
||||
for (auto *eventsList : GetEventsListsNotAssociatedToScene(project)) {
|
||||
eventLists.push_back(eventsList);
|
||||
}
|
||||
return eventLists;
|
||||
}
|
||||
|
||||
const void SetupEvents(gd::EventsList &eventList) {
|
||||
|
||||
// Add some free functions usages in events
|
||||
@@ -310,38 +285,6 @@ const void SetupEvents(gd::EventsList &eventList) {
|
||||
event.GetActions().Insert(action);
|
||||
eventList.InsertEvent(event);
|
||||
}
|
||||
|
||||
if (eventList.GetEventsCount() != FreeFunctionWithGroup) {
|
||||
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
|
||||
}
|
||||
// Create an event referring to a group.
|
||||
{
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction action;
|
||||
action.SetType("MyExtension::DoSomethingWithObjects");
|
||||
action.SetParametersCount(2);
|
||||
action.SetParameter(0, gd::Expression("GroupWithMyBehavior"));
|
||||
action.SetParameter(1, gd::Expression("MyCustomObject"));
|
||||
event.GetActions().Insert(action);
|
||||
eventList.InsertEvent(event);
|
||||
}
|
||||
|
||||
if (eventList.GetEventsCount() != FreeFunctionWithObjectExpressionOnGroup) {
|
||||
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
|
||||
}
|
||||
// Create an event referring to a group in an expression.
|
||||
{
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction action;
|
||||
action.SetType("MyExtension::DoSomething");
|
||||
action.SetParametersCount(1);
|
||||
action.SetParameter(
|
||||
0,
|
||||
gd::Expression(
|
||||
"GroupWithMyBehavior.GetObjectNumber()"));
|
||||
event.GetActions().Insert(action);
|
||||
eventList.InsertEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Add some events based behavior usages in events
|
||||
@@ -878,7 +821,7 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
|
||||
behaviorAction.GetParameters().push_back(
|
||||
gd::ParameterMetadata()
|
||||
.SetName("ObjectWithMyBehavior")
|
||||
.SetName("OtherObject")
|
||||
.SetType("object")
|
||||
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
|
||||
behaviorAction.GetParameters().push_back(
|
||||
@@ -886,8 +829,6 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
.SetName("OtherBehavior")
|
||||
.SetType("behavior")
|
||||
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
|
||||
auto &group = behaviorAction.GetObjectGroups().InsertNew("GroupWithMyBehavior");
|
||||
group.AddObject("ObjectWithMyBehavior");
|
||||
|
||||
auto &behaviorExpression =
|
||||
behaviorEventsFunctions
|
||||
@@ -1068,8 +1009,6 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
auto &childObject = eventsBasedObject.InsertNewObject(
|
||||
project, "MyExtension::Sprite", "ObjectWithMyBehavior", 0);
|
||||
childObject.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior", "MyBehavior");
|
||||
auto &group = eventsBasedObject.GetObjectGroups().InsertNew("GroupWithMyBehavior");
|
||||
group.AddObject(childObject.GetName());
|
||||
|
||||
eventsBasedObject.InsertNewObject(
|
||||
project, "MyEventsExtension::MyEventsBasedObject", "MyCustomObject", 1);
|
||||
@@ -1140,8 +1079,6 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
.SetName("MyCustomObject")
|
||||
.SetType("object")
|
||||
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
|
||||
auto &group = action.GetObjectGroups().InsertNew("GroupWithMyBehavior");
|
||||
group.AddObject("ObjectWithMyBehavior");
|
||||
}
|
||||
|
||||
// Add some usages in events
|
||||
@@ -1154,8 +1091,6 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
auto &object = layout.InsertNewObject(project, "MyExtension::Sprite",
|
||||
"ObjectWithMyBehavior", 0);
|
||||
object.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior", "MyBehavior");
|
||||
auto &group = layout.GetObjectGroups().InsertNew("GroupWithMyBehavior", 0);
|
||||
group.AddObject("ObjectWithMyBehavior");
|
||||
|
||||
auto &globalObject = project.InsertNewObject(
|
||||
project, "MyExtension::Sprite", "GlobalObjectWithMyBehavior", 0);
|
||||
@@ -1294,29 +1229,6 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
REQUIRE(externalLayout2.GetInitialInstances().HasInstancesOfObject(
|
||||
"GlobalObject1") == false);
|
||||
}
|
||||
|
||||
SECTION("Events") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &layout = project.GetLayout("Scene");
|
||||
|
||||
// Trigger the refactoring after removing an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRemovedInLayout(
|
||||
project, layout, "ObjectWithMyBehavior", /* isObjectGroup=*/false);
|
||||
|
||||
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
|
||||
// Check actions with the object in parameters have been removed.
|
||||
REQUIRE(
|
||||
AreActionsEmpty(eventsList->GetEvent(FreeFunctionWithObjects)));
|
||||
|
||||
// Check actions with the object in expressions have been removed.
|
||||
REQUIRE(AreActionsEmpty(
|
||||
eventsList->GetEvent(FreeFunctionWithObjectExpression)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Object renamed (in layout)") {
|
||||
@@ -1435,7 +1347,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
REQUIRE(externalLayout2.GetInitialInstances().HasInstancesOfObject(
|
||||
"GlobalObject3") == true);
|
||||
}
|
||||
|
||||
|
||||
SECTION("Events") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
@@ -1446,145 +1358,57 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInLayout(
|
||||
project, layout, "ObjectWithMyBehavior",
|
||||
"RenamedObjectWithMyBehavior",
|
||||
project, layout, "ObjectWithMyBehavior", "RenamedObjectWithMyBehavior",
|
||||
/* isObjectGroup=*/false);
|
||||
|
||||
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
|
||||
// Check object name has been renamed in action parameters.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(eventsList->GetEvent(
|
||||
FreeFunctionWithObjects)) == "RenamedObjectWithMyBehavior");
|
||||
// Check object name has been renamed in action parameters.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(
|
||||
layout.GetEvents().GetEvent(FreeFunctionWithObjects)) ==
|
||||
"RenamedObjectWithMyBehavior");
|
||||
|
||||
// Check object name has been renamed in expressions.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(
|
||||
eventsList->GetEvent(FreeFunctionWithObjectExpression)) ==
|
||||
// Check object name has been renamed in expressions.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(
|
||||
layout.GetEvents().GetEvent(FreeFunctionWithObjectExpression)) ==
|
||||
"RenamedObjectWithMyBehavior.GetObjectNumber()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Group deleted (in layout)") {
|
||||
SECTION("Events") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &layout = project.GetLayout("Scene");
|
||||
|
||||
// Trigger the refactoring after removing a group
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRemovedInLayout(
|
||||
project, layout, "GroupWithMyBehavior", /* isObjectGroup=*/true);
|
||||
|
||||
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
|
||||
// Check actions with the group in parameters have been removed.
|
||||
REQUIRE(AreActionsEmpty(eventsList->GetEvent(FreeFunctionWithGroup)));
|
||||
|
||||
// Check actions with the group in expressions have been removed.
|
||||
REQUIRE(AreActionsEmpty(
|
||||
eventsList->GetEvent(FreeFunctionWithObjectExpressionOnGroup)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Group renamed (in layout)") {
|
||||
SECTION("Events") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &layout = project.GetLayout("Scene");
|
||||
|
||||
// Trigger the refactoring after the renaming of a group
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInLayout(
|
||||
project, layout, "GroupWithMyBehavior", "RenamedGroupWithMyBehavior",
|
||||
/* isObjectGroup=*/true);
|
||||
|
||||
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
|
||||
// Check group name has been renamed in action parameters.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(eventsList->GetEvent(
|
||||
FreeFunctionWithGroup)) == "RenamedGroupWithMyBehavior");
|
||||
|
||||
// Check group name has been renamed in expressions.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(eventsList->GetEvent(
|
||||
FreeFunctionWithObjectExpressionOnGroup)) ==
|
||||
"RenamedGroupWithMyBehavior.GetObjectNumber()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Object renamed (in events function)") {
|
||||
SECTION("Group") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
|
||||
// Add a (free) function with an object group
|
||||
gd::EventsFunction &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
gd::ObjectGroup &objectGroup =
|
||||
eventsFunction.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
objectGroup.AddObject("Object1");
|
||||
objectGroup.AddObject("Object2");
|
||||
// In theory, we would add the object parameters, but we're not testing
|
||||
// events in this test.
|
||||
// Add a (free) function with an object group
|
||||
gd::EventsFunction &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
gd::ObjectGroup &objectGroup =
|
||||
eventsFunction.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
objectGroup.AddObject("Object1");
|
||||
objectGroup.AddObject("Object2");
|
||||
// In theory, we would add the object parameters, but we're not testing
|
||||
// events in this test.
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer globalObjectsContainer;
|
||||
gd::ObjectsContainer objectsContainer;
|
||||
gd::ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
project, eventsFunction.GetParameters(), objectsContainer);
|
||||
// (this is strictly not necessary because we're not testing events in
|
||||
// this test)
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer globalObjectsContainer;
|
||||
gd::ObjectsContainer objectsContainer;
|
||||
gd::ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
project, eventsFunction.GetParameters(), objectsContainer);
|
||||
// (this is strictly not necessary because we're not testing events in this
|
||||
// test)
|
||||
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
|
||||
project, eventsFunction, globalObjectsContainer, objectsContainer,
|
||||
"Object1", "RenamedObject1",
|
||||
/* isObjectGroup=*/false);
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
|
||||
project, eventsFunction, globalObjectsContainer, objectsContainer,
|
||||
"Object1", "RenamedObject1",
|
||||
/* isObjectGroup=*/false);
|
||||
|
||||
REQUIRE(objectGroup.Find("Object1") == false);
|
||||
REQUIRE(objectGroup.Find("RenamedObject1") == true);
|
||||
REQUIRE(objectGroup.Find("Object2") == true);
|
||||
REQUIRE(objectGroup.Find("Object1") == false);
|
||||
REQUIRE(objectGroup.Find("RenamedObject1") == true);
|
||||
REQUIRE(objectGroup.Find("Object2") == true);
|
||||
|
||||
// Events are not tested
|
||||
}
|
||||
|
||||
SECTION("Events") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsFunction =
|
||||
eventsExtension.GetEventsFunction("MyOtherEventsFunction");
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer globalObjectsContainer;
|
||||
gd::ObjectsContainer objectsContainer;
|
||||
gd::ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
project, eventsFunction.GetParameters(), objectsContainer);
|
||||
|
||||
// Trigger the refactoring after the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
|
||||
project, eventsFunction, globalObjectsContainer, objectsContainer,
|
||||
"ObjectWithMyBehavior", "RenamedObjectWithMyBehavior",
|
||||
/* isObjectGroup=*/false);
|
||||
|
||||
// Check object name has been renamed in action parameters.
|
||||
REQUIRE(
|
||||
GetEventFirstActionFirstParameterString(
|
||||
eventsFunction.GetEvents().GetEvent(FreeFunctionWithObjects)) ==
|
||||
"RenamedObjectWithMyBehavior");
|
||||
|
||||
// Check object name has been renamed in expressions.
|
||||
REQUIRE(GetEventFirstActionFirstParameterString(
|
||||
eventsFunction.GetEvents().GetEvent(
|
||||
FreeFunctionWithObjectExpression)) ==
|
||||
"RenamedObjectWithMyBehavior.GetObjectNumber()");
|
||||
}
|
||||
// Events are not tested
|
||||
}
|
||||
|
||||
SECTION("Object renamed (in events-based object)") {
|
||||
|
@@ -1,474 +0,0 @@
|
||||
namespace gdjs {
|
||||
export interface Object3DDataContent {
|
||||
width: float;
|
||||
height: float;
|
||||
depth: float;
|
||||
}
|
||||
/** Base parameters for {@link gdjs.RuntimeObject3D} */
|
||||
export interface Object3DData extends ObjectData {
|
||||
/** The base parameters of the RuntimeObject3D */
|
||||
content: Object3DDataContent;
|
||||
}
|
||||
|
||||
const getValidDimensionValue = (value: float | undefined) =>
|
||||
value === undefined ? 100 : value <= 0 ? 1 : value;
|
||||
|
||||
/**
|
||||
* Base class for 3D objects.
|
||||
*/
|
||||
export abstract class RuntimeObject3D extends gdjs.RuntimeObject {
|
||||
/**
|
||||
* Position on the Z axis.
|
||||
*/
|
||||
private _z: float = 0;
|
||||
/**
|
||||
* `_width` takes this value when the scale equals 1.
|
||||
*
|
||||
* It can't be 0.
|
||||
*/
|
||||
private _originalWidth: float;
|
||||
/**
|
||||
* `_height` takes this value when the scale equals 1.
|
||||
*
|
||||
* It can't be 0.
|
||||
*/
|
||||
private _originalHeight: float;
|
||||
/**
|
||||
* `depth` takes this value when the scale equals 1.
|
||||
*
|
||||
* It can't be 0.
|
||||
*/
|
||||
private _originalDepth: float;
|
||||
private _width: float;
|
||||
private _height: float;
|
||||
private _depth: float;
|
||||
private _flippedX: boolean = false;
|
||||
private _flippedY: boolean = false;
|
||||
private _flippedZ: boolean = false;
|
||||
/**
|
||||
* Euler angle with the `ZYX` order.
|
||||
*
|
||||
* Note that `_rotationZ` is `angle` from `gdjs.RuntimeObject`.
|
||||
*/
|
||||
private _rotationX: float = 0;
|
||||
/**
|
||||
* Euler angle with the `ZYX` order.
|
||||
*
|
||||
* Note that `_rotationZ` is `angle` from `gdjs.RuntimeObject`.
|
||||
*/
|
||||
private _rotationY: float = 0;
|
||||
private static _temporaryVector = new THREE.Vector3();
|
||||
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
objectData: Object3DData
|
||||
) {
|
||||
super(instanceContainer, objectData);
|
||||
// TODO Should 0 be replaced by 0.01 instead of using the default value?
|
||||
this._width = this._originalWidth = getValidDimensionValue(
|
||||
objectData.content.width
|
||||
);
|
||||
this._height = this._originalHeight = getValidDimensionValue(
|
||||
objectData.content.height
|
||||
);
|
||||
this._depth = this._originalDepth = getValidDimensionValue(
|
||||
objectData.content.depth
|
||||
);
|
||||
}
|
||||
|
||||
abstract getRenderer(): gdjs.RuntimeObject3DRenderer;
|
||||
|
||||
getRendererObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
get3DRendererObject() {
|
||||
return this.getRenderer().get3DRendererObject();
|
||||
}
|
||||
|
||||
updateFromObjectData(
|
||||
oldObjectData: Object3DData,
|
||||
newObjectData: Object3DData
|
||||
): boolean {
|
||||
// There is no need to check if they changed because events can't modify them.
|
||||
this._setOriginalWidth(
|
||||
getValidDimensionValue(newObjectData.content.width)
|
||||
);
|
||||
this._setOriginalHeight(
|
||||
getValidDimensionValue(newObjectData.content.height)
|
||||
);
|
||||
this._setOriginalDepth(
|
||||
getValidDimensionValue(newObjectData.content.depth)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
|
||||
if (initialInstanceData.customSize) {
|
||||
this.setWidth(initialInstanceData.width);
|
||||
this.setHeight(initialInstanceData.height);
|
||||
}
|
||||
initialInstanceData.numberProperties.forEach((property) => {
|
||||
if (property.name === 'z') {
|
||||
this.setZ(property.value);
|
||||
} else if (property.name === 'depth') {
|
||||
if (initialInstanceData.customSize) {
|
||||
this.setDepth(property.value);
|
||||
}
|
||||
} else if (property.name === 'rotationX') {
|
||||
this.setRotationX(property.value);
|
||||
} else if (property.name === 'rotationY') {
|
||||
this.setRotationY(property.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setX(x: float): void {
|
||||
super.setX(x);
|
||||
this.getRenderer().updatePosition();
|
||||
}
|
||||
|
||||
setY(y: float): void {
|
||||
super.setY(y);
|
||||
this.getRenderer().updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the object position on the Z axis.
|
||||
*/
|
||||
setZ(z: float): void {
|
||||
if (z === this._z) return;
|
||||
this._z = z;
|
||||
this.getRenderer().updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object position on the Z axis.
|
||||
*/
|
||||
getZ(): float {
|
||||
return this._z;
|
||||
}
|
||||
|
||||
setAngle(angle: float): void {
|
||||
super.setAngle(angle);
|
||||
this.getRenderer().updateRotation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the object rotation on the X axis.
|
||||
*
|
||||
* This is an Euler angle. Objects use the `ZYX` order.
|
||||
*/
|
||||
setRotationX(angle: float): void {
|
||||
this._rotationX = angle;
|
||||
this.getRenderer().updateRotation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the object rotation on the Y axis.
|
||||
*
|
||||
* This is an Euler angle. Objects use the `ZYX` order.
|
||||
*/
|
||||
setRotationY(angle: float): void {
|
||||
this._rotationY = angle;
|
||||
this.getRenderer().updateRotation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object rotation on the X axis.
|
||||
*
|
||||
* This is an Euler angle. Objects use the `ZYX` order.
|
||||
*/
|
||||
getRotationX(): float {
|
||||
return this._rotationX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object rotation on the Y axis.
|
||||
*
|
||||
* This is an Euler angle. Objects use the `ZYX` order.
|
||||
*/
|
||||
getRotationY(): float {
|
||||
return this._rotationY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the object around the scene x axis at its center.
|
||||
* @param deltaAngle the rotation angle
|
||||
*/
|
||||
turnAroundX(deltaAngle: float): void {
|
||||
const axisX = gdjs.RuntimeObject3D._temporaryVector;
|
||||
axisX.set(1, 0, 0);
|
||||
|
||||
const mesh = this.getRenderer().get3DRendererObject();
|
||||
mesh.rotateOnWorldAxis(axisX, gdjs.toRad(deltaAngle));
|
||||
this._rotationX = gdjs.toDegrees(mesh.rotation.x);
|
||||
this._rotationY = gdjs.toDegrees(mesh.rotation.y);
|
||||
this.setAngle(gdjs.toDegrees(mesh.rotation.z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the object around the scene y axis at its center.
|
||||
* @param deltaAngle the rotation angle
|
||||
*/
|
||||
turnAroundY(deltaAngle: float): void {
|
||||
const axisY = gdjs.RuntimeObject3D._temporaryVector;
|
||||
axisY.set(0, 1, 0);
|
||||
|
||||
const mesh = this.getRenderer().get3DRendererObject();
|
||||
mesh.rotateOnWorldAxis(axisY, gdjs.toRad(deltaAngle));
|
||||
this._rotationX = gdjs.toDegrees(mesh.rotation.x);
|
||||
this._rotationY = gdjs.toDegrees(mesh.rotation.y);
|
||||
this.setAngle(gdjs.toDegrees(mesh.rotation.z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the object around the scene z axis at its center.
|
||||
* @param deltaAngle the rotation angle
|
||||
*/
|
||||
turnAroundZ(deltaAngle: float): void {
|
||||
const axisZ = gdjs.RuntimeObject3D._temporaryVector;
|
||||
axisZ.set(0, 0, 1);
|
||||
|
||||
const mesh = this.getRenderer().get3DRendererObject();
|
||||
mesh.rotateOnWorldAxis(axisZ, gdjs.toRad(deltaAngle));
|
||||
this._rotationX = gdjs.toDegrees(mesh.rotation.x);
|
||||
this._rotationY = gdjs.toDegrees(mesh.rotation.y);
|
||||
this.setAngle(gdjs.toDegrees(mesh.rotation.z));
|
||||
}
|
||||
|
||||
getWidth(): float {
|
||||
return this._width;
|
||||
}
|
||||
|
||||
getHeight(): float {
|
||||
return this._height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object size on the Z axis (called "depth").
|
||||
*/
|
||||
getDepth(): float {
|
||||
return this._depth;
|
||||
}
|
||||
|
||||
setWidth(width: float): void {
|
||||
if (this._width === width) return;
|
||||
|
||||
this._width = width;
|
||||
this.getRenderer().updateSize();
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
setHeight(height: float): void {
|
||||
if (this._height === height) return;
|
||||
|
||||
this._height = height;
|
||||
this.getRenderer().updateSize();
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the object size on the Z axis (called "depth").
|
||||
*/
|
||||
setDepth(depth: float): void {
|
||||
if (this._depth === depth) return;
|
||||
|
||||
this._depth = depth;
|
||||
this.getRenderer().updateSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the width of the object for a scale of 1.
|
||||
*
|
||||
* It can't be 0.
|
||||
*/
|
||||
_getOriginalWidth(): float {
|
||||
return this._originalWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of the object for a scale of 1.
|
||||
*
|
||||
* It can't be 0.
|
||||
*/
|
||||
_getOriginalHeight(): float {
|
||||
return this._originalHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object size on the Z axis (called "depth") when the scale equals 1.
|
||||
*/
|
||||
_getOriginalDepth(): float {
|
||||
return this._originalDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of the object for a scale of 1.
|
||||
*/
|
||||
_setOriginalWidth(originalWidth: float): void {
|
||||
if (originalWidth <= 0) {
|
||||
originalWidth = 1;
|
||||
}
|
||||
const oldOriginalWidth = this._originalWidth;
|
||||
this._originalWidth = originalWidth;
|
||||
if (oldOriginalWidth === this._width) {
|
||||
this.setWidth(originalWidth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of the object for a scale of 1.
|
||||
*/
|
||||
_setOriginalHeight(originalHeight: float): void {
|
||||
if (originalHeight <= 0) {
|
||||
originalHeight = 1;
|
||||
}
|
||||
const oldOriginalHeight = this._originalHeight;
|
||||
this._originalHeight = originalHeight;
|
||||
if (oldOriginalHeight === this._height) {
|
||||
this.setHeight(originalHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the object size on the Z axis (called "depth") when the scale equals 1.
|
||||
*/
|
||||
_setOriginalDepth(originalDepth: float): void {
|
||||
if (originalDepth <= 0) {
|
||||
originalDepth = 1;
|
||||
}
|
||||
const oldOriginalDepth = this._originalDepth;
|
||||
this._originalDepth = originalDepth;
|
||||
if (oldOriginalDepth === this._depth) {
|
||||
this.setDepth(originalDepth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the scale on X, Y and Z axis of the object.
|
||||
*
|
||||
* @param newScale The new scale (must be greater than 0).
|
||||
*/
|
||||
setScale(newScale: number): void {
|
||||
this.setScaleX(newScale);
|
||||
this.setScaleY(newScale);
|
||||
this.setScaleZ(newScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the scale on X axis of the object (changing its width).
|
||||
*
|
||||
* @param newScale The new scale (must be greater than 0).
|
||||
*/
|
||||
setScaleX(newScale: number): void {
|
||||
if (newScale < 0) {
|
||||
newScale = 0;
|
||||
}
|
||||
this.setWidth(this._originalWidth * newScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the scale on Y axis of the object (changing its height).
|
||||
*
|
||||
* @param newScale The new scale (must be greater than 0).
|
||||
*/
|
||||
setScaleY(newScale: number): void {
|
||||
if (newScale < 0) {
|
||||
newScale = 0;
|
||||
}
|
||||
this.setHeight(this._originalHeight * newScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the scale on Z axis of the object (changing its height).
|
||||
*
|
||||
* @param newScale The new scale (must be greater than 0).
|
||||
*/
|
||||
setScaleZ(newScale: number): void {
|
||||
if (newScale < 0) {
|
||||
newScale = 0;
|
||||
}
|
||||
this.setDepth(this._originalDepth * newScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scale of the object (or the geometric average of X, Y and Z scale in case they are different).
|
||||
*
|
||||
* @return the scale of the object (or the geometric average of X, Y and Z scale in case they are different).
|
||||
*/
|
||||
getScale(): number {
|
||||
const scaleX = this.getScaleX();
|
||||
const scaleY = this.getScaleY();
|
||||
const scaleZ = this.getScaleZ();
|
||||
return scaleX === scaleY && scaleX === scaleZ
|
||||
? scaleX
|
||||
: Math.pow(scaleX * scaleY * scaleZ, 1 / 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scale of the object on X axis.
|
||||
*
|
||||
* @return the scale of the object on X axis
|
||||
*/
|
||||
getScaleX(): float {
|
||||
return Math.abs(this._width / this._originalWidth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scale of the object on Y axis.
|
||||
*
|
||||
* @return the scale of the object on Y axis
|
||||
*/
|
||||
getScaleY(): float {
|
||||
return Math.abs(this._height / this._originalHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scale of the object on Z axis.
|
||||
*
|
||||
* @return the scale of the object on Z axis
|
||||
*/
|
||||
getScaleZ(): float {
|
||||
return Math.abs(this._depth / this._originalDepth);
|
||||
}
|
||||
|
||||
flipX(enable: boolean) {
|
||||
if (enable !== this._flippedX) {
|
||||
this._flippedX = enable;
|
||||
this.getRenderer().updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
flipY(enable: boolean) {
|
||||
if (enable !== this._flippedY) {
|
||||
this._flippedY = enable;
|
||||
this.getRenderer().updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
flipZ(enable: boolean) {
|
||||
if (enable !== this._flippedZ) {
|
||||
this._flippedZ = enable;
|
||||
this.getRenderer().updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
isFlippedX(): boolean {
|
||||
return this._flippedX;
|
||||
}
|
||||
|
||||
isFlippedY(): boolean {
|
||||
return this._flippedY;
|
||||
}
|
||||
|
||||
isFlippedZ(): boolean {
|
||||
return this._flippedZ;
|
||||
}
|
||||
|
||||
hide(enable: boolean): void {
|
||||
super.hide(enable);
|
||||
this.getRenderer().updateVisibility();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,55 +0,0 @@
|
||||
namespace gdjs {
|
||||
export abstract class RuntimeObject3DRenderer {
|
||||
protected _object: gdjs.RuntimeObject3D;
|
||||
private _threeObject3D: THREE.Object3D;
|
||||
|
||||
constructor(
|
||||
runtimeObject: gdjs.RuntimeObject3D,
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
threeObject3D: THREE.Object3D
|
||||
) {
|
||||
this._object = runtimeObject;
|
||||
this._threeObject3D = threeObject3D;
|
||||
this._threeObject3D.rotation.order = 'ZYX';
|
||||
|
||||
instanceContainer
|
||||
.getLayer('')
|
||||
.getRenderer()
|
||||
.add3DRendererObject(this._threeObject3D);
|
||||
}
|
||||
|
||||
get3DRendererObject() {
|
||||
return this._threeObject3D;
|
||||
}
|
||||
|
||||
updatePosition() {
|
||||
this._threeObject3D.position.set(
|
||||
this._object.x + this._object.getWidth() / 2,
|
||||
this._object.y + this._object.getHeight() / 2,
|
||||
this._object.getZ() + this._object.getDepth() / 2
|
||||
);
|
||||
}
|
||||
|
||||
updateRotation() {
|
||||
this._threeObject3D.rotation.set(
|
||||
gdjs.toRad(this._object.getRotationX()),
|
||||
gdjs.toRad(this._object.getRotationY()),
|
||||
gdjs.toRad(this._object.angle)
|
||||
);
|
||||
}
|
||||
|
||||
updateSize() {
|
||||
const object = this._object;
|
||||
this._threeObject3D.scale.set(
|
||||
object.isFlippedX() ? -object.getWidth() : object.getWidth(),
|
||||
object.isFlippedY() ? -object.getHeight() : object.getHeight(),
|
||||
object.isFlippedZ() ? -object.getDepth() : object.getDepth()
|
||||
);
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
updateVisibility() {
|
||||
this._threeObject3D.visible = !this._object.isHidden();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,73 +0,0 @@
|
||||
namespace gdjs {
|
||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||
'Scene3D::AmbientLight',
|
||||
new (class implements gdjs.PixiFiltersTools.FilterCreator {
|
||||
makeFilter(
|
||||
target: EffectsTarget,
|
||||
effectData: EffectData
|
||||
): gdjs.PixiFiltersTools.Filter {
|
||||
return new (class implements gdjs.PixiFiltersTools.Filter {
|
||||
light: THREE.AmbientLight;
|
||||
_isEnabled: boolean;
|
||||
|
||||
constructor() {
|
||||
this.light = new THREE.AmbientLight();
|
||||
this._isEnabled = false;
|
||||
}
|
||||
|
||||
isEnabled(target: EffectsTarget): boolean {
|
||||
return this._isEnabled;
|
||||
}
|
||||
setEnabled(target: EffectsTarget, enabled: boolean): boolean {
|
||||
if (this._isEnabled === enabled) {
|
||||
return true;
|
||||
}
|
||||
if (enabled) {
|
||||
return this.applyEffect(target);
|
||||
} else {
|
||||
return this.removeEffect(target);
|
||||
}
|
||||
}
|
||||
applyEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
scene.add(this.light);
|
||||
this._isEnabled = true;
|
||||
return true;
|
||||
}
|
||||
removeEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
scene.remove(this.light);
|
||||
this._isEnabled = false;
|
||||
return true;
|
||||
}
|
||||
updatePreRender(target: gdjs.EffectsTarget): any {}
|
||||
updateDoubleParameter(parameterName: string, value: number): void {
|
||||
if (parameterName === 'intensity') {
|
||||
this.light.intensity = value;
|
||||
}
|
||||
}
|
||||
updateStringParameter(parameterName: string, value: string): void {
|
||||
if (parameterName === 'color') {
|
||||
this.light.color = new THREE.Color(
|
||||
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value)
|
||||
);
|
||||
}
|
||||
}
|
||||
updateBooleanParameter(parameterName: string, value: boolean): void {}
|
||||
})();
|
||||
}
|
||||
})()
|
||||
);
|
||||
}
|
@@ -1,440 +0,0 @@
|
||||
namespace gdjs {
|
||||
/** Base parameters for {@link gdjs.Cube3DRuntimeObject} */
|
||||
export interface Cube3DObjectData extends Object3DData {
|
||||
/** The base parameters of the Cube3D object */
|
||||
content: Object3DDataContent & {
|
||||
enableTextureTransparency: boolean;
|
||||
facesOrientation: 'Y' | 'Z';
|
||||
frontFaceResourceName: string;
|
||||
backFaceResourceName: string;
|
||||
backFaceUpThroughWhichAxisRotation: 'X' | 'Y';
|
||||
leftFaceResourceName: string;
|
||||
rightFaceResourceName: string;
|
||||
topFaceResourceName: string;
|
||||
bottomFaceResourceName: string;
|
||||
frontFaceResourceRepeat: boolean;
|
||||
backFaceResourceRepeat: boolean;
|
||||
leftFaceResourceRepeat: boolean;
|
||||
rightFaceResourceRepeat: boolean;
|
||||
topFaceResourceRepeat: boolean;
|
||||
bottomFaceResourceRepeat: boolean;
|
||||
frontFaceVisible: boolean;
|
||||
backFaceVisible: boolean;
|
||||
leftFaceVisible: boolean;
|
||||
rightFaceVisible: boolean;
|
||||
topFaceVisible: boolean;
|
||||
bottomFaceVisible: boolean;
|
||||
materialType: 'Basic' | 'StandardWithoutMetalness';
|
||||
};
|
||||
}
|
||||
|
||||
type FaceName = 'front' | 'back' | 'left' | 'right' | 'top' | 'bottom';
|
||||
const faceNameToBitmaskIndex = {
|
||||
front: 0,
|
||||
back: 1,
|
||||
left: 2,
|
||||
right: 3,
|
||||
top: 4,
|
||||
bottom: 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows a 3D box object.
|
||||
*/
|
||||
export class Cube3DRuntimeObject extends gdjs.RuntimeObject3D {
|
||||
private _renderer: Cube3DRuntimeObjectRenderer;
|
||||
private _facesOrientation: 'Y' | 'Z';
|
||||
private _backFaceUpThroughWhichAxisRotation: 'X' | 'Y';
|
||||
private _shouldUseTransparentTexture: boolean;
|
||||
// `_rotationZ` is `angle` from `gdjs.RuntimeObject`.
|
||||
private _visibleFacesBitmask: integer;
|
||||
private _textureRepeatFacesBitmask: integer;
|
||||
private _faceResourceNames: [
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string
|
||||
];
|
||||
_materialType: gdjs.Cube3DRuntimeObject.MaterialType =
|
||||
gdjs.Cube3DRuntimeObject.MaterialType.Basic;
|
||||
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
objectData: Cube3DObjectData
|
||||
) {
|
||||
super(instanceContainer, objectData);
|
||||
this._shouldUseTransparentTexture =
|
||||
objectData.content.enableTextureTransparency || false;
|
||||
this._facesOrientation = objectData.content.facesOrientation || 'Y';
|
||||
this._visibleFacesBitmask = 0;
|
||||
if (objectData.content.frontFaceVisible)
|
||||
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['front'];
|
||||
if (objectData.content.backFaceVisible)
|
||||
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['back'];
|
||||
if (objectData.content.leftFaceVisible)
|
||||
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['left'];
|
||||
if (objectData.content.rightFaceVisible)
|
||||
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['right'];
|
||||
if (objectData.content.topFaceVisible)
|
||||
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['top'];
|
||||
if (objectData.content.bottomFaceVisible)
|
||||
this._visibleFacesBitmask |= 1 << faceNameToBitmaskIndex['bottom'];
|
||||
this._textureRepeatFacesBitmask = 0;
|
||||
if (objectData.content.frontFaceResourceRepeat)
|
||||
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['front'];
|
||||
if (objectData.content.backFaceResourceRepeat)
|
||||
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['back'];
|
||||
if (objectData.content.leftFaceResourceRepeat)
|
||||
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['left'];
|
||||
if (objectData.content.rightFaceResourceRepeat)
|
||||
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['right'];
|
||||
if (objectData.content.topFaceResourceRepeat)
|
||||
this._textureRepeatFacesBitmask |= 1 << faceNameToBitmaskIndex['top'];
|
||||
if (objectData.content.bottomFaceResourceRepeat)
|
||||
this._textureRepeatFacesBitmask |=
|
||||
1 << faceNameToBitmaskIndex['bottom'];
|
||||
this._backFaceUpThroughWhichAxisRotation =
|
||||
objectData.content.backFaceUpThroughWhichAxisRotation || 'X';
|
||||
this._faceResourceNames = [
|
||||
objectData.content.frontFaceResourceName,
|
||||
objectData.content.backFaceResourceName,
|
||||
objectData.content.leftFaceResourceName,
|
||||
objectData.content.rightFaceResourceName,
|
||||
objectData.content.topFaceResourceName,
|
||||
objectData.content.bottomFaceResourceName,
|
||||
];
|
||||
this._materialType = this._convertMaterialType(
|
||||
objectData.content.materialType
|
||||
);
|
||||
|
||||
this._renderer = new gdjs.Cube3DRuntimeObjectRenderer(
|
||||
this,
|
||||
instanceContainer
|
||||
);
|
||||
|
||||
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
|
||||
this.onCreated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the visibility of a face of the 3D box.
|
||||
*
|
||||
* @param faceName - The name of the face to set visibility for.
|
||||
* @param value - The visibility value to set.
|
||||
*/
|
||||
setFaceVisibility(faceName: FaceName, enable: boolean) {
|
||||
const faceIndex = faceNameToBitmaskIndex[faceName];
|
||||
if (faceIndex === undefined) {
|
||||
return;
|
||||
}
|
||||
if (enable === this.isFaceAtIndexVisible(faceIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
this._visibleFacesBitmask |= 1 << faceIndex;
|
||||
} else {
|
||||
this._visibleFacesBitmask &= ~(1 << faceIndex);
|
||||
}
|
||||
this._renderer.updateFace(faceIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the texture repeat of a face of the 3D box.
|
||||
*
|
||||
* @param faceName - The name of the face to set visibility for.
|
||||
* @param value - The visibility value to set.
|
||||
*/
|
||||
setRepeatTextureOnFace(faceName: FaceName, enable: boolean) {
|
||||
const faceIndex = faceNameToBitmaskIndex[faceName];
|
||||
if (faceIndex === undefined) {
|
||||
return;
|
||||
}
|
||||
if (enable === this.shouldRepeatTextureOnFaceAtIndex(faceIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
this._textureRepeatFacesBitmask |= 1 << faceIndex;
|
||||
} else {
|
||||
this._textureRepeatFacesBitmask &= ~(1 << faceIndex);
|
||||
}
|
||||
this._renderer.updateFace(faceIndex);
|
||||
}
|
||||
|
||||
isFaceVisible(faceName: FaceName): boolean {
|
||||
const faceIndex = faceNameToBitmaskIndex[faceName];
|
||||
if (faceIndex === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.isFaceAtIndexVisible(faceIndex);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
isFaceAtIndexVisible(faceIndex): boolean {
|
||||
return (this._visibleFacesBitmask & (1 << faceIndex)) !== 0;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
shouldRepeatTextureOnFaceAtIndex(faceIndex): boolean {
|
||||
return (this._textureRepeatFacesBitmask & (1 << faceIndex)) !== 0;
|
||||
}
|
||||
|
||||
setFaceResourceName(faceName: FaceName, resourceName: string): void {
|
||||
const faceIndex = faceNameToBitmaskIndex[faceName];
|
||||
if (faceIndex === undefined) {
|
||||
return;
|
||||
}
|
||||
if (this._faceResourceNames[faceIndex] === resourceName) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._faceResourceNames[faceIndex] = resourceName;
|
||||
this._renderer.updateFace(faceIndex);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
getFaceAtIndexResourceName(faceIndex: integer): string {
|
||||
return this._faceResourceNames[faceIndex];
|
||||
}
|
||||
|
||||
getRenderer(): gdjs.RuntimeObject3DRenderer {
|
||||
return this._renderer;
|
||||
}
|
||||
|
||||
getBackFaceUpThroughWhichAxisRotation(): 'X' | 'Y' {
|
||||
return this._backFaceUpThroughWhichAxisRotation;
|
||||
}
|
||||
|
||||
setBackFaceUpThroughWhichAxisRotation(axis: 'X' | 'Y'): void {
|
||||
this._backFaceUpThroughWhichAxisRotation = axis;
|
||||
this._renderer.updateFace(faceNameToBitmaskIndex['back']);
|
||||
}
|
||||
|
||||
getFacesOrientation(): 'Y' | 'Z' {
|
||||
return this._facesOrientation;
|
||||
}
|
||||
|
||||
setFacesOrientation(orientation: 'Y' | 'Z'): void {
|
||||
this._facesOrientation = orientation;
|
||||
this._renderer.updateFace(faceNameToBitmaskIndex['left']);
|
||||
this._renderer.updateFace(faceNameToBitmaskIndex['right']);
|
||||
this._renderer.updateFace(faceNameToBitmaskIndex['top']);
|
||||
// Bottom texture should not change based on that setting.
|
||||
}
|
||||
|
||||
updateFromObjectData(
|
||||
oldObjectData: Cube3DObjectData,
|
||||
newObjectData: Cube3DObjectData
|
||||
): boolean {
|
||||
super.updateFromObjectData(oldObjectData, newObjectData);
|
||||
if (
|
||||
oldObjectData.content.frontFaceVisible !==
|
||||
newObjectData.content.frontFaceVisible
|
||||
) {
|
||||
this.setFaceVisibility('front', newObjectData.content.frontFaceVisible);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.backFaceVisible !==
|
||||
newObjectData.content.backFaceVisible
|
||||
) {
|
||||
this.setFaceVisibility('back', newObjectData.content.backFaceVisible);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.leftFaceVisible !==
|
||||
newObjectData.content.leftFaceVisible
|
||||
) {
|
||||
this.setFaceVisibility('left', newObjectData.content.leftFaceVisible);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.rightFaceVisible !==
|
||||
newObjectData.content.rightFaceVisible
|
||||
) {
|
||||
this.setFaceVisibility('right', newObjectData.content.rightFaceVisible);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.topFaceVisible !==
|
||||
newObjectData.content.topFaceVisible
|
||||
) {
|
||||
this.setFaceVisibility('top', newObjectData.content.topFaceVisible);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.bottomFaceVisible !==
|
||||
newObjectData.content.bottomFaceVisible
|
||||
) {
|
||||
this.setFaceVisibility(
|
||||
'bottom',
|
||||
newObjectData.content.bottomFaceVisible
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.frontFaceResourceName !==
|
||||
newObjectData.content.frontFaceResourceName
|
||||
) {
|
||||
this.setFaceResourceName(
|
||||
'front',
|
||||
newObjectData.content.frontFaceResourceName
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.backFaceResourceName !==
|
||||
newObjectData.content.backFaceResourceName
|
||||
) {
|
||||
this.setFaceResourceName(
|
||||
'back',
|
||||
newObjectData.content.backFaceResourceName
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.leftFaceResourceName !==
|
||||
newObjectData.content.leftFaceResourceName
|
||||
) {
|
||||
this.setFaceResourceName(
|
||||
'left',
|
||||
newObjectData.content.leftFaceResourceName
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.rightFaceResourceName !==
|
||||
newObjectData.content.rightFaceResourceName
|
||||
) {
|
||||
this.setFaceResourceName(
|
||||
'right',
|
||||
newObjectData.content.rightFaceResourceName
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.topFaceResourceName !==
|
||||
newObjectData.content.topFaceResourceName
|
||||
) {
|
||||
this.setFaceResourceName(
|
||||
'top',
|
||||
newObjectData.content.topFaceResourceName
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.bottomFaceResourceName !==
|
||||
newObjectData.content.bottomFaceResourceName
|
||||
) {
|
||||
this.setFaceResourceName(
|
||||
'bottom',
|
||||
newObjectData.content.bottomFaceResourceName
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.frontFaceResourceRepeat !==
|
||||
newObjectData.content.frontFaceResourceRepeat
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'front',
|
||||
newObjectData.content.frontFaceResourceRepeat
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.backFaceResourceRepeat !==
|
||||
newObjectData.content.backFaceResourceRepeat
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'back',
|
||||
newObjectData.content.backFaceResourceRepeat
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.leftFaceResourceRepeat !==
|
||||
newObjectData.content.leftFaceResourceRepeat
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'left',
|
||||
newObjectData.content.leftFaceResourceRepeat
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.rightFaceResourceRepeat !==
|
||||
newObjectData.content.rightFaceResourceRepeat
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'right',
|
||||
newObjectData.content.rightFaceResourceRepeat
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.topFaceResourceRepeat !==
|
||||
newObjectData.content.topFaceResourceRepeat
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'top',
|
||||
newObjectData.content.topFaceResourceRepeat
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.bottomFaceResourceRepeat !==
|
||||
newObjectData.content.bottomFaceResourceRepeat
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'bottom',
|
||||
newObjectData.content.bottomFaceResourceRepeat
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.backFaceUpThroughWhichAxisRotation !==
|
||||
newObjectData.content.backFaceUpThroughWhichAxisRotation
|
||||
) {
|
||||
this.setBackFaceUpThroughWhichAxisRotation(
|
||||
newObjectData.content.backFaceUpThroughWhichAxisRotation
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.facesOrientation !==
|
||||
newObjectData.content.facesOrientation
|
||||
) {
|
||||
this.setFacesOrientation(newObjectData.content.facesOrientation);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.materialType !==
|
||||
newObjectData.content.materialType
|
||||
) {
|
||||
this.setMaterialType(newObjectData.content.materialType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the texture transparency should be enabled.
|
||||
*/
|
||||
shouldUseTransparentTexture(): boolean {
|
||||
return this._shouldUseTransparentTexture;
|
||||
}
|
||||
|
||||
_convertMaterialType(
|
||||
materialTypeString: string
|
||||
): gdjs.Cube3DRuntimeObject.MaterialType {
|
||||
if (materialTypeString === 'StandardWithoutMetalness') {
|
||||
return gdjs.Cube3DRuntimeObject.MaterialType.StandardWithoutMetalness;
|
||||
} else {
|
||||
return gdjs.Cube3DRuntimeObject.MaterialType.Basic;
|
||||
}
|
||||
}
|
||||
|
||||
setMaterialType(materialTypeString: string) {
|
||||
const newMaterialType = this._convertMaterialType(materialTypeString);
|
||||
if (this._materialType === newMaterialType) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._materialType = newMaterialType;
|
||||
this._renderer._updateMaterials();
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Cube3DRuntimeObject {
|
||||
export enum MaterialType {
|
||||
Basic,
|
||||
StandardWithoutMetalness,
|
||||
}
|
||||
}
|
||||
gdjs.registerObject('Scene3D::Cube3DObject', gdjs.Cube3DRuntimeObject);
|
||||
}
|
@@ -1,319 +0,0 @@
|
||||
namespace gdjs {
|
||||
// Three.js materials for a cube and the order of faces in the object is different,
|
||||
// so we keep the mapping from one to the other.
|
||||
const faceIndexToMaterialIndex = {
|
||||
3: 0, // right
|
||||
2: 1, // left
|
||||
5: 2, // bottom
|
||||
4: 3, // top
|
||||
0: 4, // front
|
||||
1: 5, // back
|
||||
};
|
||||
const materialIndexToFaceIndex = {
|
||||
0: 3,
|
||||
1: 2,
|
||||
2: 5,
|
||||
3: 4,
|
||||
4: 0,
|
||||
5: 1,
|
||||
};
|
||||
|
||||
const noRepeatTextureVertexIndexToUvMapping = {
|
||||
0: [0, 0],
|
||||
1: [1, 0],
|
||||
2: [0, 1],
|
||||
3: [1, 1],
|
||||
};
|
||||
|
||||
const noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ = {
|
||||
0: [0, 1],
|
||||
1: [0, 0],
|
||||
2: [1, 1],
|
||||
3: [1, 0],
|
||||
};
|
||||
|
||||
let transparentMaterial: THREE.MeshBasicMaterial;
|
||||
const getTransparentMaterial = () => {
|
||||
if (!transparentMaterial)
|
||||
transparentMaterial = new THREE.MeshBasicMaterial({
|
||||
transparent: true,
|
||||
opacity: 0,
|
||||
// Set the alpha test to to ensure the faces behind are rendered
|
||||
// (no "back face culling" that would still be done if alphaTest is not set).
|
||||
alphaTest: 1,
|
||||
});
|
||||
|
||||
return transparentMaterial;
|
||||
};
|
||||
|
||||
const getFaceMaterial = (
|
||||
runtimeObject: gdjs.Cube3DRuntimeObject,
|
||||
faceIndex: integer
|
||||
) => {
|
||||
if (!runtimeObject.isFaceAtIndexVisible(faceIndex))
|
||||
return getTransparentMaterial();
|
||||
|
||||
return runtimeObject
|
||||
.getInstanceContainer()
|
||||
.getGame()
|
||||
.getImageManager()
|
||||
.getThreeMaterial(runtimeObject.getFaceAtIndexResourceName(faceIndex), {
|
||||
useTransparentTexture: runtimeObject.shouldUseTransparentTexture(),
|
||||
forceBasicMaterial:
|
||||
runtimeObject._materialType ===
|
||||
gdjs.Cube3DRuntimeObject.MaterialType.Basic,
|
||||
});
|
||||
};
|
||||
|
||||
class Cube3DRuntimeObjectPixiRenderer extends gdjs.RuntimeObject3DRenderer {
|
||||
private _cube3DRuntimeObject: gdjs.Cube3DRuntimeObject;
|
||||
private _boxMesh: THREE.Mesh;
|
||||
|
||||
constructor(
|
||||
runtimeObject: gdjs.Cube3DRuntimeObject,
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer
|
||||
) {
|
||||
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
||||
// TODO (3D) - feature: support color instead of texture?
|
||||
const materials = [
|
||||
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[0]),
|
||||
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[1]),
|
||||
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[2]),
|
||||
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[3]),
|
||||
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[4]),
|
||||
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[5]),
|
||||
];
|
||||
const boxMesh = new THREE.Mesh(geometry, materials);
|
||||
|
||||
super(runtimeObject, instanceContainer, boxMesh);
|
||||
this._boxMesh = boxMesh;
|
||||
this._cube3DRuntimeObject = runtimeObject;
|
||||
|
||||
this.updateSize();
|
||||
this.updatePosition();
|
||||
this.updateRotation();
|
||||
}
|
||||
|
||||
updateFace(faceIndex: integer) {
|
||||
const materialIndex = faceIndexToMaterialIndex[faceIndex];
|
||||
if (materialIndex === undefined) return;
|
||||
|
||||
this._boxMesh.material[materialIndex] = getFaceMaterial(
|
||||
this._cube3DRuntimeObject,
|
||||
faceIndex
|
||||
);
|
||||
if (this._cube3DRuntimeObject.isFaceAtIndexVisible(faceIndex)) {
|
||||
this.updateTextureUvMapping(faceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
updateSize(): void {
|
||||
super.updateSize();
|
||||
this.updateTextureUvMapping();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the UV mapping of the geometry in order to repeat a material
|
||||
* over the different faces of the cube.
|
||||
* The mesh must be configured with a list of materials in order
|
||||
* for the method to work.
|
||||
* @param faceIndex The face index to update. If undefined, updates all the faces.
|
||||
*/
|
||||
updateTextureUvMapping(faceIndex?: number) {
|
||||
// @ts-ignore - position is stored as a Float32BufferAttribute
|
||||
const pos: THREE.BufferAttribute = this._boxMesh.geometry.getAttribute(
|
||||
'position'
|
||||
);
|
||||
// @ts-ignore - uv is stored as a Float32BufferAttribute
|
||||
const uvMapping: THREE.BufferAttribute = this._boxMesh.geometry.getAttribute(
|
||||
'uv'
|
||||
);
|
||||
const startIndex =
|
||||
faceIndex === undefined ? 0 : faceIndexToMaterialIndex[faceIndex] * 4;
|
||||
const endIndex =
|
||||
faceIndex === undefined
|
||||
? 23
|
||||
: faceIndexToMaterialIndex[faceIndex] * 4 + 3;
|
||||
for (
|
||||
let vertexIndex = startIndex;
|
||||
vertexIndex <= endIndex;
|
||||
vertexIndex++
|
||||
) {
|
||||
const materialIndex = Math.floor(
|
||||
vertexIndex /
|
||||
// Each face of the cube has 4 points
|
||||
4
|
||||
);
|
||||
const material = this._boxMesh.material[materialIndex];
|
||||
if (!material || !material.map) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const shouldRepeatTexture = this._cube3DRuntimeObject.shouldRepeatTextureOnFaceAtIndex(
|
||||
materialIndexToFaceIndex[materialIndex]
|
||||
);
|
||||
|
||||
const shouldOrientateFacesTowardsY =
|
||||
this._cube3DRuntimeObject.getFacesOrientation() === 'Y';
|
||||
|
||||
let x: float, y: float;
|
||||
switch (materialIndex) {
|
||||
case 0:
|
||||
// Right face
|
||||
if (shouldRepeatTexture) {
|
||||
if (shouldOrientateFacesTowardsY) {
|
||||
x =
|
||||
-(this._boxMesh.scale.z / material.map.source.data.width) *
|
||||
(pos.getZ(vertexIndex) - 0.5);
|
||||
y =
|
||||
-(this._boxMesh.scale.y / material.map.source.data.height) *
|
||||
(pos.getY(vertexIndex) + 0.5);
|
||||
} else {
|
||||
x =
|
||||
-(this._boxMesh.scale.y / material.map.source.data.width) *
|
||||
(pos.getY(vertexIndex) - 0.5);
|
||||
y =
|
||||
(this._boxMesh.scale.z / material.map.source.data.height) *
|
||||
(pos.getZ(vertexIndex) - 0.5);
|
||||
}
|
||||
} else {
|
||||
if (shouldOrientateFacesTowardsY) {
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
} else {
|
||||
[
|
||||
x,
|
||||
y,
|
||||
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// Left face
|
||||
if (shouldRepeatTexture) {
|
||||
if (shouldOrientateFacesTowardsY) {
|
||||
x =
|
||||
(this._boxMesh.scale.z / material.map.source.data.width) *
|
||||
(pos.getZ(vertexIndex) + 0.5);
|
||||
y =
|
||||
-(this._boxMesh.scale.y / material.map.source.data.height) *
|
||||
(pos.getY(vertexIndex) + 0.5);
|
||||
} else {
|
||||
x =
|
||||
(this._boxMesh.scale.y / material.map.source.data.width) *
|
||||
(pos.getY(vertexIndex) + 0.5);
|
||||
y =
|
||||
(this._boxMesh.scale.z / material.map.source.data.height) *
|
||||
(pos.getZ(vertexIndex) - 0.5);
|
||||
}
|
||||
} else {
|
||||
if (shouldOrientateFacesTowardsY) {
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
} else {
|
||||
[
|
||||
x,
|
||||
y,
|
||||
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
x = -x;
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// Bottom face
|
||||
if (shouldRepeatTexture) {
|
||||
x =
|
||||
(this._boxMesh.scale.x / material.map.source.data.width) *
|
||||
(pos.getX(vertexIndex) + 0.5);
|
||||
y =
|
||||
(this._boxMesh.scale.z / material.map.source.data.height) *
|
||||
(pos.getZ(vertexIndex) - 0.5);
|
||||
} else {
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// Top face
|
||||
if (shouldRepeatTexture) {
|
||||
if (shouldOrientateFacesTowardsY) {
|
||||
x =
|
||||
(this._boxMesh.scale.x / material.map.source.data.width) *
|
||||
(pos.getX(vertexIndex) + 0.5);
|
||||
y =
|
||||
-(this._boxMesh.scale.z / material.map.source.data.height) *
|
||||
(pos.getZ(vertexIndex) + 0.5);
|
||||
} else {
|
||||
x =
|
||||
-(this._boxMesh.scale.x / material.map.source.data.width) *
|
||||
(pos.getX(vertexIndex) - 0.5);
|
||||
y =
|
||||
(this._boxMesh.scale.z / material.map.source.data.height) *
|
||||
(pos.getZ(vertexIndex) - 0.5);
|
||||
}
|
||||
} else {
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
if (!shouldOrientateFacesTowardsY) {
|
||||
x = -x;
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
// Front face
|
||||
if (shouldRepeatTexture) {
|
||||
x =
|
||||
(this._boxMesh.scale.x / material.map.source.data.width) *
|
||||
(pos.getX(vertexIndex) + 0.5);
|
||||
y =
|
||||
-(this._boxMesh.scale.y / material.map.source.data.height) *
|
||||
(pos.getY(vertexIndex) + 0.5);
|
||||
} else {
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
// Back face
|
||||
const shouldBackFaceBeUpThroughXAxisRotation =
|
||||
this._cube3DRuntimeObject.getBackFaceUpThroughWhichAxisRotation() ===
|
||||
'X';
|
||||
|
||||
if (shouldRepeatTexture) {
|
||||
x =
|
||||
(shouldBackFaceBeUpThroughXAxisRotation ? 1 : -1) *
|
||||
(this._boxMesh.scale.x / material.map.source.data.width) *
|
||||
(pos.getX(vertexIndex) +
|
||||
(shouldBackFaceBeUpThroughXAxisRotation ? 1 : -1) * 0.5);
|
||||
y =
|
||||
(shouldBackFaceBeUpThroughXAxisRotation ? 1 : -1) *
|
||||
(this._boxMesh.scale.y / material.map.source.data.height) *
|
||||
(pos.getY(vertexIndex) +
|
||||
(shouldBackFaceBeUpThroughXAxisRotation ? -1 : 1) * 0.5);
|
||||
} else {
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
if (shouldBackFaceBeUpThroughXAxisRotation) {
|
||||
x = -x;
|
||||
y = -y;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
}
|
||||
uvMapping.setXY(vertexIndex, x, y);
|
||||
}
|
||||
uvMapping.needsUpdate = true;
|
||||
}
|
||||
|
||||
_updateMaterials() {
|
||||
for (let index = 0; index < 6; index++) {
|
||||
this.updateFace(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const Cube3DRuntimeObjectRenderer = Cube3DRuntimeObjectPixiRenderer;
|
||||
export type Cube3DRuntimeObjectRenderer = Cube3DRuntimeObjectPixiRenderer;
|
||||
}
|
@@ -1,101 +0,0 @@
|
||||
namespace gdjs {
|
||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||
'Scene3D::DirectionalLight',
|
||||
new (class implements gdjs.PixiFiltersTools.FilterCreator {
|
||||
makeFilter(
|
||||
target: EffectsTarget,
|
||||
effectData: EffectData
|
||||
): gdjs.PixiFiltersTools.Filter {
|
||||
return new (class implements gdjs.PixiFiltersTools.Filter {
|
||||
light: THREE.DirectionalLight;
|
||||
rotationObject: THREE.Group;
|
||||
_isEnabled: boolean = false;
|
||||
top: string = 'Y-';
|
||||
elevation: float = 45;
|
||||
rotation: float = 0;
|
||||
|
||||
constructor() {
|
||||
this.light = new THREE.DirectionalLight();
|
||||
this.light.position.set(1, 0, 0);
|
||||
this.rotationObject = new THREE.Group();
|
||||
this.rotationObject.add(this.light);
|
||||
this.updateRotation();
|
||||
}
|
||||
|
||||
isEnabled(target: EffectsTarget): boolean {
|
||||
return this._isEnabled;
|
||||
}
|
||||
setEnabled(target: EffectsTarget, enabled: boolean): boolean {
|
||||
if (this._isEnabled === enabled) {
|
||||
return true;
|
||||
}
|
||||
if (enabled) {
|
||||
return this.applyEffect(target);
|
||||
} else {
|
||||
return this.removeEffect(target);
|
||||
}
|
||||
}
|
||||
applyEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
scene.add(this.rotationObject);
|
||||
this._isEnabled = true;
|
||||
return true;
|
||||
}
|
||||
removeEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene) {
|
||||
return false;
|
||||
}
|
||||
scene.remove(this.rotationObject);
|
||||
this._isEnabled = false;
|
||||
return true;
|
||||
}
|
||||
updatePreRender(target: gdjs.EffectsTarget): any {}
|
||||
updateDoubleParameter(parameterName: string, value: number): void {
|
||||
if (parameterName === 'intensity') {
|
||||
this.light.intensity = value;
|
||||
} else if (parameterName === 'elevation') {
|
||||
this.elevation = value;
|
||||
this.updateRotation();
|
||||
} else if (parameterName === 'rotation') {
|
||||
this.rotation = value;
|
||||
this.updateRotation();
|
||||
}
|
||||
}
|
||||
updateStringParameter(parameterName: string, value: string): void {
|
||||
if (parameterName === 'color') {
|
||||
this.light.color = new THREE.Color(
|
||||
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value)
|
||||
);
|
||||
}
|
||||
if (parameterName === 'top') {
|
||||
this.top = value;
|
||||
this.updateRotation();
|
||||
}
|
||||
}
|
||||
updateBooleanParameter(parameterName: string, value: boolean): void {}
|
||||
updateRotation() {
|
||||
if (this.top === 'Z+') {
|
||||
// 0° is a light from the right of the screen.
|
||||
this.rotationObject.rotation.z = gdjs.toRad(this.rotation);
|
||||
this.rotationObject.rotation.y = -gdjs.toRad(this.elevation);
|
||||
} else {
|
||||
// 0° becomes a light from Z+.
|
||||
this.rotationObject.rotation.y = gdjs.toRad(this.rotation) - 90;
|
||||
this.rotationObject.rotation.z = -gdjs.toRad(this.elevation);
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
})()
|
||||
);
|
||||
}
|
@@ -1,70 +0,0 @@
|
||||
namespace gdjs {
|
||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||
'Scene3D::ExponentialFog',
|
||||
new (class implements gdjs.PixiFiltersTools.FilterCreator {
|
||||
makeFilter(
|
||||
target: EffectsTarget,
|
||||
effectData: EffectData
|
||||
): gdjs.PixiFiltersTools.Filter {
|
||||
return new (class implements gdjs.PixiFiltersTools.Filter {
|
||||
fog: THREE.FogExp2;
|
||||
|
||||
constructor() {
|
||||
this.fog = new THREE.FogExp2(0xffffff);
|
||||
}
|
||||
|
||||
isEnabled(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
return scene ? scene.fog === this.fog : false;
|
||||
}
|
||||
setEnabled(target: EffectsTarget, enabled: boolean): boolean {
|
||||
if (enabled) {
|
||||
return this.applyEffect(target);
|
||||
} else {
|
||||
return this.removeEffect(target);
|
||||
}
|
||||
}
|
||||
applyEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene || scene.fog === undefined) {
|
||||
return false;
|
||||
}
|
||||
scene.fog = this.fog;
|
||||
return true;
|
||||
}
|
||||
removeEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene || scene.fog === undefined) {
|
||||
return false;
|
||||
}
|
||||
scene.fog = null;
|
||||
return true;
|
||||
}
|
||||
updatePreRender(target: gdjs.EffectsTarget): any {}
|
||||
updateDoubleParameter(parameterName: string, value: number): void {
|
||||
if (parameterName === 'density') {
|
||||
this.fog.density = value;
|
||||
}
|
||||
}
|
||||
updateStringParameter(parameterName: string, value: string): void {
|
||||
if (parameterName === 'color') {
|
||||
this.fog.color = new THREE.Color(
|
||||
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value)
|
||||
);
|
||||
}
|
||||
}
|
||||
updateBooleanParameter(parameterName: string, value: boolean): void {}
|
||||
})();
|
||||
}
|
||||
})()
|
||||
);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,72 +0,0 @@
|
||||
namespace gdjs {
|
||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||
'Scene3D::LinearFog',
|
||||
new (class implements gdjs.PixiFiltersTools.FilterCreator {
|
||||
makeFilter(
|
||||
target: EffectsTarget,
|
||||
effectData: EffectData
|
||||
): gdjs.PixiFiltersTools.Filter {
|
||||
return new (class implements gdjs.PixiFiltersTools.Filter {
|
||||
fog: THREE.Fog;
|
||||
|
||||
constructor() {
|
||||
this.fog = new THREE.Fog(0xffffff);
|
||||
}
|
||||
|
||||
isEnabled(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
return scene ? scene.fog === this.fog : false;
|
||||
}
|
||||
setEnabled(target: EffectsTarget, enabled: boolean): boolean {
|
||||
if (enabled) {
|
||||
return this.applyEffect(target);
|
||||
} else {
|
||||
return this.removeEffect(target);
|
||||
}
|
||||
}
|
||||
applyEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene || scene.fog === undefined) {
|
||||
return false;
|
||||
}
|
||||
scene.fog = this.fog;
|
||||
return true;
|
||||
}
|
||||
removeEffect(target: EffectsTarget): boolean {
|
||||
const scene = target.get3DRendererObject() as
|
||||
| THREE.Scene
|
||||
| null
|
||||
| undefined;
|
||||
if (!scene || scene.fog === undefined) {
|
||||
return false;
|
||||
}
|
||||
scene.fog = null;
|
||||
return true;
|
||||
}
|
||||
updatePreRender(target: gdjs.EffectsTarget): any {}
|
||||
updateDoubleParameter(parameterName: string, value: number): void {
|
||||
if (parameterName === 'near') {
|
||||
this.fog.near = value;
|
||||
} else if (parameterName === 'far') {
|
||||
this.fog.far = value;
|
||||
}
|
||||
}
|
||||
updateStringParameter(parameterName: string, value: string): void {
|
||||
if (parameterName === 'color') {
|
||||
this.fog.color = new THREE.Color(
|
||||
gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value)
|
||||
);
|
||||
}
|
||||
}
|
||||
updateBooleanParameter(parameterName: string, value: boolean): void {}
|
||||
})();
|
||||
}
|
||||
})()
|
||||
);
|
||||
}
|
@@ -1,116 +0,0 @@
|
||||
namespace gdjs {
|
||||
/** Base parameters for {@link gdjs.Cube3DRuntimeObject} */
|
||||
export interface Model3DObjectData extends Object3DData {
|
||||
/** The base parameters of the Model3D object */
|
||||
content: Object3DDataContent & {
|
||||
modelResourceName: string;
|
||||
rotationX: number;
|
||||
rotationY: number;
|
||||
rotationZ: number;
|
||||
keepAspectRatio: boolean;
|
||||
materialType: 'Basic' | 'StandardWithoutMetalness' | 'KeepOriginal';
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A 3D object which displays a 3D model.
|
||||
*/
|
||||
export class Model3DRuntimeObject extends gdjs.RuntimeObject3D {
|
||||
_renderer: gdjs.Model3DRuntimeObjectRenderer;
|
||||
|
||||
_modelResourceName: string;
|
||||
_materialType: gdjs.Model3DRuntimeObject.MaterialType =
|
||||
gdjs.Model3DRuntimeObject.MaterialType.Basic;
|
||||
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
objectData: Model3DObjectData
|
||||
) {
|
||||
super(instanceContainer, objectData);
|
||||
this._modelResourceName = objectData.content.modelResourceName;
|
||||
this._renderer = new gdjs.Model3DRuntimeObjectRenderer(
|
||||
this,
|
||||
instanceContainer
|
||||
);
|
||||
this._updateMaterialType(objectData);
|
||||
|
||||
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
|
||||
this.onCreated();
|
||||
}
|
||||
|
||||
updateFromObjectData(
|
||||
oldObjectData: Model3DObjectData,
|
||||
newObjectData: Model3DObjectData
|
||||
): boolean {
|
||||
super.updateFromObjectData(oldObjectData, newObjectData);
|
||||
if (
|
||||
oldObjectData.content.width !== newObjectData.content.width ||
|
||||
oldObjectData.content.height !== newObjectData.content.height ||
|
||||
oldObjectData.content.depth !== newObjectData.content.depth ||
|
||||
oldObjectData.content.rotationX !== newObjectData.content.rotationX ||
|
||||
oldObjectData.content.rotationY !== newObjectData.content.rotationY ||
|
||||
oldObjectData.content.rotationZ !== newObjectData.content.rotationZ ||
|
||||
oldObjectData.content.keepAspectRatio !==
|
||||
newObjectData.content.keepAspectRatio
|
||||
) {
|
||||
this._updateDefaultTransformation(newObjectData);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.materialType !==
|
||||
newObjectData.content.materialType
|
||||
) {
|
||||
this._updateMaterialType(newObjectData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_updateDefaultTransformation(objectData: Model3DObjectData) {
|
||||
const rotationX = objectData.content.rotationX || 0;
|
||||
const rotationY = objectData.content.rotationY || 0;
|
||||
const rotationZ = objectData.content.rotationZ || 0;
|
||||
const keepAspectRatio = objectData.content.keepAspectRatio;
|
||||
this._renderer._updateDefaultTransformation(
|
||||
rotationX,
|
||||
rotationY,
|
||||
rotationZ,
|
||||
this._getOriginalWidth(),
|
||||
this._getOriginalHeight(),
|
||||
this._getOriginalDepth(),
|
||||
keepAspectRatio
|
||||
);
|
||||
}
|
||||
|
||||
getRenderer(): RuntimeObject3DRenderer {
|
||||
return this._renderer;
|
||||
}
|
||||
|
||||
_convertMaterialType(
|
||||
materialTypeString: string
|
||||
): gdjs.Model3DRuntimeObject.MaterialType {
|
||||
if (materialTypeString === 'KeepOriginal') {
|
||||
return gdjs.Model3DRuntimeObject.MaterialType.KeepOriginal;
|
||||
} else if (materialTypeString === 'StandardWithoutMetalness') {
|
||||
return gdjs.Model3DRuntimeObject.MaterialType.StandardWithoutMetalness;
|
||||
} else {
|
||||
return gdjs.Model3DRuntimeObject.MaterialType.Basic;
|
||||
}
|
||||
}
|
||||
|
||||
_updateMaterialType(objectData: Model3DObjectData) {
|
||||
this._materialType = this._convertMaterialType(
|
||||
objectData.content.materialType
|
||||
);
|
||||
this._renderer._updateMaterials();
|
||||
this._updateDefaultTransformation(objectData);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Model3DRuntimeObject {
|
||||
export enum MaterialType {
|
||||
Basic,
|
||||
StandardWithoutMetalness,
|
||||
KeepOriginal,
|
||||
}
|
||||
}
|
||||
gdjs.registerObject('Scene3D::Model3DObject', gdjs.Model3DRuntimeObject);
|
||||
}
|
@@ -1,184 +0,0 @@
|
||||
namespace gdjs {
|
||||
class Model3DRuntimeObject3DRenderer extends gdjs.RuntimeObject3DRenderer {
|
||||
private _model3DRuntimeObject: gdjs.Model3DRuntimeObject;
|
||||
/**
|
||||
* The 3D model stretched in a 1x1x1 cube.
|
||||
*/
|
||||
private _threeObject: THREE.Object3D;
|
||||
|
||||
constructor(
|
||||
runtimeObject: gdjs.Model3DRuntimeObject,
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer
|
||||
) {
|
||||
// @ts-ignore It can't be null if THREE exists.
|
||||
const originalModelMesh: THREE.Object3D = instanceContainer
|
||||
.getGame()
|
||||
.getModel3DManager()
|
||||
.getModel(runtimeObject._modelResourceName);
|
||||
const modelObject3D = originalModelMesh.clone();
|
||||
|
||||
// Create a group to transform the object according to
|
||||
// position, angle and dimensions.
|
||||
const group = new THREE.Group();
|
||||
group.rotation.order = 'ZYX';
|
||||
group.add(modelObject3D);
|
||||
super(runtimeObject, instanceContainer, group);
|
||||
|
||||
this._model3DRuntimeObject = runtimeObject;
|
||||
this._threeObject = modelObject3D;
|
||||
|
||||
this.updateSize();
|
||||
this.updatePosition();
|
||||
this.updateRotation();
|
||||
}
|
||||
|
||||
_updateDefaultTransformation(
|
||||
rotationX: float,
|
||||
rotationY: float,
|
||||
rotationZ: float,
|
||||
originalWidth: float,
|
||||
originalHeight: float,
|
||||
originalDepth: float,
|
||||
keepAspectRatio: boolean
|
||||
) {
|
||||
const boundingBox = this._getModelAABB(rotationX, rotationY, rotationZ);
|
||||
|
||||
// Center the model.
|
||||
this._threeObject.position.set(
|
||||
-(boundingBox.min.x + boundingBox.max.x) / 2,
|
||||
(this._threeObject.position.y =
|
||||
-(boundingBox.min.y + boundingBox.max.y) / 2),
|
||||
(this._threeObject.position.z =
|
||||
-(boundingBox.min.z + boundingBox.max.z) / 2)
|
||||
);
|
||||
|
||||
// Rotate the model.
|
||||
this._threeObject.scale.set(1, 1, 1);
|
||||
this._threeObject.rotation.set(
|
||||
gdjs.toRad(rotationX),
|
||||
gdjs.toRad(rotationY),
|
||||
gdjs.toRad(rotationZ)
|
||||
);
|
||||
|
||||
// Stretch the model in a 1x1x1 cube.
|
||||
const modelWidth = boundingBox.max.x - boundingBox.min.x;
|
||||
const modelHeight = boundingBox.max.y - boundingBox.min.y;
|
||||
const modelDepth = boundingBox.max.z - boundingBox.min.z;
|
||||
|
||||
const scaleX = 1 / modelWidth;
|
||||
const scaleY = 1 / modelHeight;
|
||||
const scaleZ = 1 / modelDepth;
|
||||
|
||||
const scaleMatrix = new THREE.Matrix4();
|
||||
scaleMatrix.makeScale(scaleX, scaleY, scaleZ);
|
||||
this._threeObject.updateMatrix();
|
||||
this._threeObject.applyMatrix4(scaleMatrix);
|
||||
|
||||
if (keepAspectRatio) {
|
||||
// Reduce the object dimensions to keep aspect ratio.
|
||||
const widthRatio = originalWidth / modelWidth;
|
||||
const heightRatio = originalHeight / modelHeight;
|
||||
const depthRatio = originalDepth / modelDepth;
|
||||
const scaleRatio = Math.min(widthRatio, heightRatio, depthRatio);
|
||||
|
||||
this._object._setOriginalWidth(scaleRatio * modelWidth);
|
||||
this._object._setOriginalHeight(scaleRatio * modelHeight);
|
||||
this._object._setOriginalDepth(scaleRatio * modelDepth);
|
||||
}
|
||||
|
||||
this._threeObject.updateMatrix();
|
||||
}
|
||||
|
||||
private _getModelAABB(
|
||||
rotationX: float,
|
||||
rotationY: float,
|
||||
rotationZ: float
|
||||
) {
|
||||
// The original model is used because `setFromObject` is working in
|
||||
// world transformation.
|
||||
|
||||
// @ts-ignore It can't be null if THREE exists.
|
||||
const originalModelMesh: THREE.Object3D = this._object
|
||||
.getInstanceContainer()
|
||||
.getGame()
|
||||
.getModel3DManager()
|
||||
.getModel(this._model3DRuntimeObject._modelResourceName);
|
||||
|
||||
originalModelMesh.rotation.set(
|
||||
gdjs.toRad(rotationX),
|
||||
gdjs.toRad(rotationY),
|
||||
gdjs.toRad(rotationZ)
|
||||
);
|
||||
|
||||
const aabb = new THREE.Box3().setFromObject(originalModelMesh);
|
||||
|
||||
// Revert changes.
|
||||
originalModelMesh.rotation.set(0, 0, 0);
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
_updateMaterials() {
|
||||
// @ts-ignore It can't be null if THREE exists.
|
||||
const originalModelMesh: THREE.Object3D = this._model3DRuntimeObject
|
||||
.getInstanceContainer()
|
||||
.getGame()
|
||||
.getModel3DManager()
|
||||
.getModel(this._model3DRuntimeObject._modelResourceName);
|
||||
const modelObject3D = originalModelMesh.clone();
|
||||
|
||||
this.get3DRendererObject().remove(this._threeObject);
|
||||
this.get3DRendererObject().add(modelObject3D);
|
||||
|
||||
this._threeObject = modelObject3D;
|
||||
|
||||
this._replaceMaterials();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace materials to better work with lights (or no light).
|
||||
*/
|
||||
_replaceMaterials() {
|
||||
if (
|
||||
this._model3DRuntimeObject._materialType ===
|
||||
gdjs.Model3DRuntimeObject.MaterialType.StandardWithoutMetalness
|
||||
) {
|
||||
this._threeObject.traverse((node) => {
|
||||
if (node.type === 'Mesh') {
|
||||
const mesh = node as THREE.Mesh;
|
||||
const material = mesh.material as THREE.MeshStandardMaterial;
|
||||
//@ts-ignore
|
||||
if (material.metalness) {
|
||||
//@ts-ignore
|
||||
material.metalness = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (
|
||||
this._model3DRuntimeObject._materialType ===
|
||||
gdjs.Model3DRuntimeObject.MaterialType.Basic
|
||||
) {
|
||||
this._threeObject.traverse((node) => {
|
||||
if (node.type === 'Mesh') {
|
||||
const mesh = node as THREE.Mesh;
|
||||
const basicMaterial = new THREE.MeshBasicMaterial();
|
||||
//@ts-ignore
|
||||
if (mesh.material.color) {
|
||||
//@ts-ignore
|
||||
basicMaterial.color = mesh.material.color;
|
||||
}
|
||||
//@ts-ignore
|
||||
if (mesh.material.map) {
|
||||
//@ts-ignore
|
||||
basicMaterial.map = mesh.material.map;
|
||||
}
|
||||
mesh.material = basicMaterial;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const Model3DRuntimeObjectRenderer = Model3DRuntimeObject3DRenderer;
|
||||
export type Model3DRuntimeObjectRenderer = Model3DRuntimeObject3DRenderer;
|
||||
}
|
@@ -1,235 +0,0 @@
|
||||
namespace gdjs {
|
||||
export namespace scene3d {
|
||||
const assumedFovIn2D = 45;
|
||||
|
||||
export namespace camera {
|
||||
export const getCameraZ = (
|
||||
runtimeScene: RuntimeScene,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
): float => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
const fov = threeCamera ? threeCamera.fov : assumedFovIn2D;
|
||||
return layer.getCameraZ(fov, cameraIndex);
|
||||
};
|
||||
|
||||
export const setCameraZ = (
|
||||
runtimeScene: RuntimeScene,
|
||||
z: float,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
) => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
const fov = threeCamera ? threeCamera.fov : assumedFovIn2D;
|
||||
layer.setCameraZ(z, fov, cameraIndex);
|
||||
};
|
||||
|
||||
export const getCameraRotationX = (
|
||||
runtimeScene: RuntimeScene,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
): float => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return 0;
|
||||
return gdjs.toDegrees(threeCamera.rotation.x);
|
||||
};
|
||||
|
||||
export const setCameraRotationX = (
|
||||
runtimeScene: RuntimeScene,
|
||||
angle: float,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
) => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return;
|
||||
|
||||
threeCamera.rotation.x = gdjs.toRad(angle);
|
||||
};
|
||||
|
||||
export const getCameraRotationY = (
|
||||
runtimeScene: RuntimeScene,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
): float => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return 0;
|
||||
return gdjs.toDegrees(threeCamera.rotation.y);
|
||||
};
|
||||
|
||||
export const setCameraRotationY = (
|
||||
runtimeScene: RuntimeScene,
|
||||
angle: float,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
) => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return;
|
||||
|
||||
threeCamera.rotation.y = gdjs.toRad(angle);
|
||||
};
|
||||
|
||||
export const turnCameraTowardObject = (
|
||||
runtimeScene: RuntimeScene,
|
||||
object: gdjs.RuntimeObject,
|
||||
layerName: string,
|
||||
cameraIndex: integer,
|
||||
isStandingOnY: boolean
|
||||
) => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return;
|
||||
|
||||
if (isStandingOnY) {
|
||||
threeCamera.up.set(0, 1, 0);
|
||||
} else {
|
||||
threeCamera.up.set(0, 0, 1);
|
||||
}
|
||||
threeCamera.lookAt(
|
||||
object.getCenterXInScene(),
|
||||
-object.getCenterYInScene(),
|
||||
//@ts-ignore
|
||||
object.getZ ? object.getZ() : 0
|
||||
);
|
||||
// The layer angle takes over the 3D camera Z rotation.
|
||||
layer.setCameraRotation(gdjs.toDegrees(-threeCamera.rotation.z));
|
||||
};
|
||||
|
||||
export const turnCameraTowardPosition = (
|
||||
runtimeScene: RuntimeScene,
|
||||
x: float,
|
||||
y: float,
|
||||
z: float,
|
||||
layerName: string,
|
||||
cameraIndex: integer,
|
||||
isStandingOnY: boolean
|
||||
) => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return;
|
||||
|
||||
if (isStandingOnY) {
|
||||
threeCamera.up.set(0, 1, 0);
|
||||
} else {
|
||||
threeCamera.up.set(0, 0, 1);
|
||||
}
|
||||
threeCamera.lookAt(x, -y, z);
|
||||
// The layer angle takes over the 3D camera Z rotation.
|
||||
layer.setCameraRotation(gdjs.toDegrees(-threeCamera.rotation.z));
|
||||
};
|
||||
|
||||
export const getNearPlane = (
|
||||
runtimeScene: RuntimeScene,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
): float => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return 0;
|
||||
return threeCamera.near;
|
||||
};
|
||||
|
||||
export const setNearPlane = (
|
||||
runtimeScene: RuntimeScene,
|
||||
distance: float,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
) => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return;
|
||||
|
||||
threeCamera.near = Math.min(
|
||||
// 0 is not a valid value for three js perspective camera:
|
||||
// https://threejs.org/docs/#api/en/cameras/PerspectiveCamera.
|
||||
Math.max(distance, 0.0001),
|
||||
// Near value cannot exceed far value.
|
||||
threeCamera.far
|
||||
);
|
||||
layerRenderer.setThreeCameraDirty(true);
|
||||
};
|
||||
|
||||
export const getFarPlane = (
|
||||
runtimeScene: RuntimeScene,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
): float => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return 0;
|
||||
return threeCamera.far;
|
||||
};
|
||||
|
||||
export const setFarPlane = (
|
||||
runtimeScene: RuntimeScene,
|
||||
distance: float,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
) => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return;
|
||||
|
||||
// Far value cannot be lower than near value
|
||||
threeCamera.far = Math.max(distance, threeCamera.near);
|
||||
layerRenderer.setThreeCameraDirty(true);
|
||||
};
|
||||
|
||||
export const getFov = (
|
||||
runtimeScene: RuntimeScene,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
): float => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return 45;
|
||||
return threeCamera.fov;
|
||||
};
|
||||
|
||||
export const setFov = (
|
||||
runtimeScene: RuntimeScene,
|
||||
angle: float,
|
||||
layerName: string,
|
||||
cameraIndex: integer
|
||||
) => {
|
||||
const layer = runtimeScene.getLayer(layerName);
|
||||
const layerRenderer = layer.getRenderer();
|
||||
|
||||
const threeCamera = layerRenderer.getThreeCamera();
|
||||
if (!threeCamera) return;
|
||||
|
||||
threeCamera.fov = Math.min(Math.max(angle, 0), 180);
|
||||
layerRenderer.setThreeCameraDirty(true);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@@ -147,7 +147,7 @@ module.exports = {
|
||||
.addCondition(
|
||||
'AppOpenErrored',
|
||||
_('App open errored'),
|
||||
_('Check if there was an error while loading the app open.'),
|
||||
_('Check if there was a error while loading the app open.'),
|
||||
_('App open had an error'),
|
||||
'',
|
||||
'JsPlatform/Extensions/admobicon24.png',
|
||||
@@ -181,7 +181,7 @@ module.exports = {
|
||||
)
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Display in landscape? (portrait otherwise)'),
|
||||
_('Display in landscape? (portait otherwise)'),
|
||||
'',
|
||||
false
|
||||
)
|
||||
|
@@ -117,7 +117,7 @@ namespace gdjs {
|
||||
|
||||
await admob.start();
|
||||
|
||||
logger.info('AdMob successfully started.');
|
||||
logger.info('AdMob succesfully started.');
|
||||
admobStarted = true;
|
||||
},
|
||||
false
|
||||
|
@@ -439,7 +439,7 @@ module.exports = {
|
||||
|
||||
/**
|
||||
* You can optionally add sanity tests that will check the basic working
|
||||
* of your extension behaviors/objects by instantiating behaviors/objects
|
||||
* of your extension behaviors/objects by instanciating behaviors/objects
|
||||
* and setting the property to a given value.
|
||||
*
|
||||
* If you don't have any tests, you can simply return an empty array.
|
||||
@@ -606,7 +606,7 @@ module.exports = {
|
||||
);
|
||||
|
||||
if (this._instance.hasCustomSize() && this._pixiObject) {
|
||||
const customWidth = this.getCustomWidth();
|
||||
const customWidth = this._instance.getCustomWidth();
|
||||
if (
|
||||
this._pixiObject &&
|
||||
this._pixiObject._style.wordWrapWidth !== customWidth
|
||||
|
50
Extensions/BBText/pixi-multistyle-text/README.md
vendored
50
Extensions/BBText/pixi-multistyle-text/README.md
vendored
@@ -12,32 +12,31 @@ In the example below, we are defining 4 text styles.
|
||||
```js
|
||||
let text = new MultiStyleText("Let's make some <ml>multiline</ml>\nand <ms>multistyle</ms> text for\n<pixi>Pixi.js!</pixi>",
|
||||
{
|
||||
"default": {
|
||||
fontFamily: "Arial",
|
||||
fontSize: "24px",
|
||||
fill: "#cccccc",
|
||||
align: "center"
|
||||
},
|
||||
"ml": {
|
||||
fontStyle: "italic",
|
||||
fill: "#ff8888"
|
||||
},
|
||||
"ms": {
|
||||
fontStyle: "italic",
|
||||
fill: "#4488ff"
|
||||
},
|
||||
"pixi": {
|
||||
fontSize: "64px",
|
||||
fill: "#efefef"
|
||||
}
|
||||
"default": {
|
||||
fontFamily: "Arial",
|
||||
fontSize: "24px",
|
||||
fill: "#cccccc",
|
||||
align: "center"
|
||||
},
|
||||
"ml": {
|
||||
fontStyle: "italic",
|
||||
fill: "#ff8888"
|
||||
},
|
||||
"ms": {
|
||||
fontStyle: "italic",
|
||||
fill: "#4488ff"
|
||||
},
|
||||
"pixi": {
|
||||
fontSize: "64px",
|
||||
fill: "#efefef"
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Build instructions
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
yarn build
|
||||
```
|
||||
$ yarn install
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -47,7 +46,6 @@ yarn build
|
||||
Creates a new `MultiStyleText` with the given text and styles.
|
||||
|
||||
#### `textStyles`
|
||||
|
||||
Type: `{ [key: string]: ExtendedTextStyle }`
|
||||
|
||||
Each key of this dictionary should match with a tag in the text. Use the key `default` for the default style.
|
||||
@@ -59,10 +57,10 @@ The `align`, `wordWrap`, `wordWrapWidth`, and `breakWord` properties are ignored
|
||||
If text is rendered without any value assigned to a given parameter, Pixi's defaults are used.
|
||||
|
||||
## Demo
|
||||
|
||||
```bash
|
||||
yarn demo
|
||||
```
|
||||
$ yarn demo
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
|
@@ -392,7 +392,7 @@ module.exports = {
|
||||
|
||||
/**
|
||||
* You can optionally add sanity tests that will check the basic working
|
||||
* of your extension behaviors/objects by instantiating behaviors/objects
|
||||
* of your extension behaviors/objects by instanciating behaviors/objects
|
||||
* and setting the property to a given value.
|
||||
*
|
||||
* If you don't have any tests, you can simply return an empty array.
|
||||
@@ -554,7 +554,7 @@ module.exports = {
|
||||
if (!texture.valid) {
|
||||
// Post pone texture update if texture is not loaded.
|
||||
// (otherwise, the bitmap font would not get updated when the
|
||||
// texture is loaded and updated).
|
||||
// texture is loaded and udpated).
|
||||
return new Promise((resolve) => {
|
||||
texture.once('update', () => {
|
||||
resolve(loadBitmapFont());
|
||||
@@ -711,7 +711,7 @@ module.exports = {
|
||||
const wordWrap = properties.get('wordWrap').getValue() === 'true';
|
||||
if (wordWrap && this._instance.hasCustomSize()) {
|
||||
this._pixiObject.maxWidth =
|
||||
this.getCustomWidth() / this._pixiObject.scale.x;
|
||||
this._instance.getCustomWidth() / this._pixiObject.scale.x;
|
||||
this._pixiObject.dirty = true;
|
||||
} else {
|
||||
this._pixiObject.maxWidth = 0;
|
||||
|
@@ -14,7 +14,7 @@ namespace gdjs {
|
||||
/**
|
||||
* Vibrate the mobile device in a pattern.
|
||||
* You can add multiple comma separated values where every second one determines the silence between vibrations.
|
||||
* Example: "200,1000,500" (200ms vibration, 1sec silence, 500ms vibration)
|
||||
* Example: "200,1000,500" (200ms vibration, 1sec silense, 500ms vibration)
|
||||
* @param intervals Comma separated list of values (in ms).
|
||||
*/
|
||||
export const startVibrationPattern = function (intervals: string) {
|
||||
|
@@ -1,12 +1,11 @@
|
||||
# bondage.js [](https://travis-ci.org/jhayley/bondage.js)
|
||||
|
||||
[Yarn](https://github.com/InfiniteAmmoInc/Yarn) parser for Javascript, in the same vein as [YarnSpinner](https://github.com/thesecretlab/YarnSpinner).
|
||||
|
||||
# Usage
|
||||
|
||||
#### As a Web Tool
|
||||
|
||||
To run through your yarn files in your browser, go to <http://hayley.zone/bondage.js>, paste your yarn data in the field, then hit "compile".
|
||||
To run through your yarn files in your browser, go to http://hayley.zone/bondage.js, paste your yarn data in the field, then hit "compile".
|
||||
|
||||
#### As a Command Line Tool
|
||||
Installation: `npm install -g bondage`
|
||||
|
@@ -103,7 +103,7 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
// Autoscroll commands so the user doesn't have to press again.
|
||||
// Autoscroll commands so the user doesnt have to press again
|
||||
if (
|
||||
gdjs.dialogueTree._isLineTypeCommand() &&
|
||||
this.dialogueDataType === 'text' &&
|
||||
@@ -458,7 +458,7 @@ namespace gdjs {
|
||||
*
|
||||
* There are three types:
|
||||
* - text - regular dialogue text is being parsed at the moment
|
||||
* - options - the player has reached a branching choice moment where they must select one of multiple options
|
||||
* - options - the player has reached a branching choise moment where they must select one of multiple options
|
||||
* - command - a <<command>> was called in the background, that can be used to trigger game events, but will not be displayed in the dialogue box.
|
||||
*
|
||||
* @param type The type you want to check for ( one of the three above )
|
||||
@@ -485,7 +485,7 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a branch exists. It is also used internally whenever you use the start from action.
|
||||
* Check if a branch exists. It is also used internaly whenever you use the start from action.
|
||||
* @param branchName The Dialogue Branch name you want to check.
|
||||
*/
|
||||
gdjs.dialogueTree.hasDialogueBranch = function (branchName: string) {
|
||||
|
@@ -48,7 +48,6 @@ module.exports = {
|
||||
'Adjust gamma, contrast, saturation, brightness, alpha or color-channel shift.'
|
||||
)
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-adjustment.js')
|
||||
.addIncludeFile('Extensions/Effects/adjustment-pixi-filter.js');
|
||||
const adjustmentProperties = adjustmentEffect.getProperties();
|
||||
@@ -97,7 +96,6 @@ module.exports = {
|
||||
.addEffect('AdvancedBloom')
|
||||
.setFullName(_('Advanced bloom'))
|
||||
.setDescription(_('Applies a bloom effect.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-kawase-blur.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/Effects/pixi-filters/filter-advanced-bloom.js'
|
||||
@@ -140,7 +138,6 @@ module.exports = {
|
||||
.addEffect('Ascii')
|
||||
.setFullName(_('ASCII'))
|
||||
.setDescription(_('Render the image with ASCII characters only.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-ascii.js')
|
||||
.addIncludeFile('Extensions/Effects/ascii-pixi-filter.js');
|
||||
const asciiProperties = asciiEffect.getProperties();
|
||||
@@ -154,7 +151,6 @@ module.exports = {
|
||||
.addEffect('Bevel')
|
||||
.setFullName(_('Beveled edges'))
|
||||
.setDescription(_('Add beveled edges around the rendered image.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-bevel.js')
|
||||
.addIncludeFile('Extensions/Effects/bevel-pixi-filter.js');
|
||||
const bevelProperties = bevelEffect.getProperties();
|
||||
@@ -198,7 +194,6 @@ module.exports = {
|
||||
.addEffect('BlackAndWhite')
|
||||
.setFullName(_('Black and White'))
|
||||
.setDescription(_('Alter the colors to make the image black and white'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/black-and-white-pixi-filter.js');
|
||||
const blackAndWhiteProperties = blackAndWhiteEffect.getProperties();
|
||||
blackAndWhiteProperties
|
||||
@@ -213,7 +208,6 @@ module.exports = {
|
||||
.setDescription(
|
||||
_('Alter the rendered image with the specified blend mode.')
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/blending-mode-pixi-filter.js');
|
||||
const blendingModeProperties = blendingModeEffect.getProperties();
|
||||
blendingModeProperties
|
||||
@@ -231,7 +225,6 @@ module.exports = {
|
||||
.addEffect('Blur')
|
||||
.setFullName(_('Blur (Gaussian, slow - prefer to use Kawase blur)'))
|
||||
.setDescription(_('Blur the rendered image. This is slow, so prefer to use Kawase blur in most cases.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/blur-pixi-filter.js');
|
||||
const blurProperties = blurEffect.getProperties();
|
||||
blurProperties
|
||||
@@ -263,7 +256,6 @@ module.exports = {
|
||||
.addEffect('Brightness')
|
||||
.setFullName(_('Brightness'))
|
||||
.setDescription(_('Make the image brighter.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/brightness-pixi-filter.js');
|
||||
const brightnessProperties = brightnessEffect.getProperties();
|
||||
brightnessProperties
|
||||
@@ -276,7 +268,6 @@ module.exports = {
|
||||
.addEffect('BulgePinch')
|
||||
.setFullName(_('Bulge Pinch'))
|
||||
.setDescription(_('Bulges or pinches the image in a circle.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-bulge-pinch.js')
|
||||
.addIncludeFile('Extensions/Effects/bulge-pinch-pixi-filter.js');
|
||||
const bulgePinchProperties = bulgePinchEffect.getProperties();
|
||||
@@ -308,7 +299,6 @@ module.exports = {
|
||||
.addEffect('ColorMap')
|
||||
.setFullName(_('Color Map'))
|
||||
.setDescription(_('Change the color rendered on screen.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/color-map-pixi-filter.js')
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-color-map.js');
|
||||
const colorMapProperties = colorMapEffect.getProperties();
|
||||
@@ -319,7 +309,7 @@ module.exports = {
|
||||
.setLabel(_('Color map texture for the effect'))
|
||||
.setDescription(
|
||||
_(
|
||||
'You can change colors of pixels by modifying a reference color image, containing each colors, called the *Color Map Texture*. To get started, **download** [a default color map texture here](https://wiki.gdevelop.io/gdevelop5/interface/scene-editor/layer-effects).'
|
||||
'You can change colors of pixels by modifing a reference color image, containing each colors, called the *Color Map Texture*. To get started, **download** [a default color map texture here](https://wiki.gdevelop.io/gdevelop5/interface/scene-editor/layer-effects).'
|
||||
)
|
||||
);
|
||||
colorMapProperties
|
||||
@@ -338,7 +328,6 @@ module.exports = {
|
||||
.addEffect('ColorReplace')
|
||||
.setFullName(_('Color Replace'))
|
||||
.setDescription(_('Effect replacing a color (or similar) by another.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-color-replace.js')
|
||||
.addIncludeFile('Extensions/Effects/color-replace-pixi-filter.js');
|
||||
const colorReplaceProperties = colorReplaceEffect.getProperties();
|
||||
@@ -369,7 +358,6 @@ module.exports = {
|
||||
.addEffect('CRT')
|
||||
.setFullName(_('CRT'))
|
||||
.setDescription(_('Apply an effect resembling old CRT monitors.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-crt.js')
|
||||
.addIncludeFile('Extensions/Effects/crt-pixi-filter.js');
|
||||
const crtProperties = crtEffect.getProperties();
|
||||
@@ -447,7 +435,6 @@ module.exports = {
|
||||
'Uses the pixel values from the specified texture (called the displacement map) to perform a displacement of an object.'
|
||||
)
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/displacement-pixi-filter.js');
|
||||
const displacementProperties = displacementEffect.getProperties();
|
||||
displacementProperties
|
||||
@@ -479,7 +466,6 @@ module.exports = {
|
||||
'Applies a dotscreen effect making objects appear to be made out of black and white halftone dots like an old printer.'
|
||||
)
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-dot.js')
|
||||
.addIncludeFile('Extensions/Effects/dot-pixi-filter.js');
|
||||
const dotProperties = dotEffect.getProperties();
|
||||
@@ -500,7 +486,6 @@ module.exports = {
|
||||
.addEffect('DropShadow')
|
||||
.setFullName(_('Drop shadow'))
|
||||
.setDescription(_('Add a shadow around the rendered image.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-kawase-blur.js')
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-drop-shadow.js')
|
||||
.addIncludeFile('Extensions/Effects/drop-shadow-pixi-filter.js');
|
||||
@@ -551,7 +536,6 @@ module.exports = {
|
||||
.addEffect('Glitch')
|
||||
.setFullName(_('Glitch'))
|
||||
.setDescription(_('Applies a glitch effect to an object.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-glitch.js')
|
||||
.addIncludeFile('Extensions/Effects/glitch-pixi-filter.js');
|
||||
const glitchProperties = glitchEffect.getProperties();
|
||||
@@ -642,7 +626,6 @@ module.exports = {
|
||||
.addEffect('Glow')
|
||||
.setFullName(_('Glow'))
|
||||
.setDescription(_('Add a glow effect around the rendered image.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-glow.js')
|
||||
.addIncludeFile('Extensions/Effects/glow-pixi-filter.js');
|
||||
const glowProperties = glowEffect.getProperties();
|
||||
@@ -671,7 +654,6 @@ module.exports = {
|
||||
.addEffect('Godray')
|
||||
.setFullName(_('Godray'))
|
||||
.setDescription(_('Apply and animate atmospheric light rays.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-godray.js')
|
||||
.addIncludeFile('Extensions/Effects/godray-pixi-filter.js');
|
||||
const godrayProperties = godrayEffect.getProperties();
|
||||
@@ -731,7 +713,6 @@ module.exports = {
|
||||
.setDescription(
|
||||
_('Blur the rendered image, with much better performance than Gaussian blur.')
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-kawase-blur.js')
|
||||
.addIncludeFile('Extensions/Effects/kawase-blur-pixi-filter.js');
|
||||
const kawaseBlurProperties = kawaseBlurEffect.getProperties();
|
||||
@@ -766,7 +747,6 @@ module.exports = {
|
||||
.addEffect('LightNight')
|
||||
.setFullName(_('Light Night'))
|
||||
.setDescription(_('Alter the colors to simulate night.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/light-night-pixi-filter.js');
|
||||
const lightNightProperties = lightNightEffect.getProperties();
|
||||
lightNightProperties
|
||||
@@ -779,7 +759,6 @@ module.exports = {
|
||||
.addEffect('Night')
|
||||
.setFullName(_('Dark Night'))
|
||||
.setDescription(_('Alter the colors to simulate a dark night.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/night-pixi-filter.js');
|
||||
const nightProperties = nightEffect.getProperties();
|
||||
nightProperties
|
||||
@@ -797,7 +776,6 @@ module.exports = {
|
||||
.addEffect('Noise')
|
||||
.setFullName(_('Noise'))
|
||||
.setDescription(_('Add some noise on the rendered image.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/noise-pixi-filter.js');
|
||||
const noiseProperties = noiseEffect.getProperties();
|
||||
noiseProperties
|
||||
@@ -810,7 +788,6 @@ module.exports = {
|
||||
.addEffect('OldFilm')
|
||||
.setFullName(_('Old Film'))
|
||||
.setDescription(_('Add a Old film effect around the rendered image.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-old-film.js')
|
||||
.addIncludeFile('Extensions/Effects/old-film-pixi-filter.js');
|
||||
const oldFilmProperties = oldFilmEffect.getProperties();
|
||||
@@ -881,7 +858,6 @@ module.exports = {
|
||||
.addEffect('Outline')
|
||||
.setFullName(_('Outline'))
|
||||
.setDescription(_('Draws an outline around the rendered image.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-outline.js')
|
||||
.addIncludeFile('Extensions/Effects/outline-pixi-filter.js');
|
||||
const outlineProperties = outlineEffect.getProperties();
|
||||
@@ -908,7 +884,6 @@ module.exports = {
|
||||
.setDescription(
|
||||
_("Applies a pixelate effect, making display objects appear 'blocky'.")
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-pixelate.js')
|
||||
.addIncludeFile('Extensions/Effects/pixelate-pixi-filter.js');
|
||||
const pixelateProperties = pixelateEffect.getProperties();
|
||||
@@ -923,7 +898,6 @@ module.exports = {
|
||||
.addEffect('RadialBlur')
|
||||
.setFullName(_('Radial Blur'))
|
||||
.setDescription(_('Applies a Motion blur to an object.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-radial-blur.js')
|
||||
.addIncludeFile('Extensions/Effects/radial-blur-pixi-filter.js')
|
||||
.markAsNotWorkingForObjects(); // See https://github.com/pixijs/filters/issues/304
|
||||
@@ -971,7 +945,6 @@ module.exports = {
|
||||
'Applies a reflection effect to simulate the reflection on water with waves.'
|
||||
)
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-reflection.js')
|
||||
.addIncludeFile('Extensions/Effects/reflection-pixi-filter.js');
|
||||
const reflectionProperties = reflectionEffect.getProperties();
|
||||
@@ -1041,7 +1014,6 @@ module.exports = {
|
||||
.setDescription(
|
||||
_('Applies a RGB split effect also known as chromatic aberration.')
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-rgb-split.js')
|
||||
.addIncludeFile('Extensions/Effects/rgb-split-pixi-filter.js');
|
||||
const rgbSplitProperties = rgbSplitEffect.getProperties();
|
||||
@@ -1080,7 +1052,6 @@ module.exports = {
|
||||
.addEffect('Sepia')
|
||||
.setFullName(_('Sepia'))
|
||||
.setDescription(_('Alter the colors to sepia.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/sepia-pixi-filter.js');
|
||||
const sepiaProperties = sepiaEffect.getProperties();
|
||||
sepiaProperties
|
||||
@@ -1093,7 +1064,6 @@ module.exports = {
|
||||
.addEffect('TiltShift')
|
||||
.setFullName(_('Tilt shift'))
|
||||
.setDescription(_('Render a tilt-shift-like camera effect.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-tilt-shift.js')
|
||||
.addIncludeFile('Extensions/Effects/tilt-shift-pixi-filter.js');
|
||||
const tiltShiftProperties = tiltShiftEffect.getProperties();
|
||||
@@ -1116,7 +1086,6 @@ module.exports = {
|
||||
'Applies a twist effect making objects appear twisted in the given direction.'
|
||||
)
|
||||
)
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-twist.js')
|
||||
.addIncludeFile('Extensions/Effects/twist-pixi-filter.js')
|
||||
.markAsNotWorkingForObjects(); // See https://github.com/pixijs/filters/issues/304
|
||||
@@ -1154,7 +1123,6 @@ module.exports = {
|
||||
.addEffect('ZoomBlur')
|
||||
.setFullName(_('Zoom blur'))
|
||||
.setDescription(_('Applies a Zoom blur.'))
|
||||
.markAsOnlyWorkingFor2D()
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-zoom-blur.js')
|
||||
.addIncludeFile('Extensions/Effects/zoom-blur-pixi-filter.js')
|
||||
.markAsNotWorkingForObjects(); // See https://github.com/pixijs/filters/issues/304
|
||||
|
@@ -1,34 +1,31 @@
|
||||
namespace gdjs {
|
||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||
'Adjustment',
|
||||
new (class extends gdjs.PixiFiltersTools.PixiFilterCreator {
|
||||
makePIXIFilter(target, effectData) {
|
||||
const adjustmentFilter = new PIXI.filters.AdjustmentFilter();
|
||||
return adjustmentFilter;
|
||||
gdjs.PixiFiltersTools.registerFilterCreator('Adjustment', {
|
||||
makePIXIFilter: function (target, effectData) {
|
||||
const adjustmentFilter = new PIXI.filters.AdjustmentFilter();
|
||||
return adjustmentFilter;
|
||||
},
|
||||
updatePreRender: function (filter, target) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const adjustmentFilter = (filter as unknown) as PIXI.filters.AdjustmentFilter;
|
||||
if (parameterName === 'gamma') {
|
||||
adjustmentFilter.gamma = value;
|
||||
} else if (parameterName === 'saturation') {
|
||||
adjustmentFilter.saturation = value;
|
||||
} else if (parameterName === 'contrast') {
|
||||
adjustmentFilter.contrast = value;
|
||||
} else if (parameterName === 'brightness') {
|
||||
adjustmentFilter.brightness = value;
|
||||
} else if (parameterName === 'red') {
|
||||
adjustmentFilter.red = value;
|
||||
} else if (parameterName === 'green') {
|
||||
adjustmentFilter.green = value;
|
||||
} else if (parameterName === 'blue') {
|
||||
adjustmentFilter.blue = value;
|
||||
} else if (parameterName === 'alpha') {
|
||||
adjustmentFilter.alpha = value;
|
||||
}
|
||||
updatePreRender(filter, target) {}
|
||||
updateDoubleParameter(filter, parameterName, value) {
|
||||
const adjustmentFilter = (filter as unknown) as PIXI.filters.AdjustmentFilter;
|
||||
if (parameterName === 'gamma') {
|
||||
adjustmentFilter.gamma = value;
|
||||
} else if (parameterName === 'saturation') {
|
||||
adjustmentFilter.saturation = value;
|
||||
} else if (parameterName === 'contrast') {
|
||||
adjustmentFilter.contrast = value;
|
||||
} else if (parameterName === 'brightness') {
|
||||
adjustmentFilter.brightness = value;
|
||||
} else if (parameterName === 'red') {
|
||||
adjustmentFilter.red = value;
|
||||
} else if (parameterName === 'green') {
|
||||
adjustmentFilter.green = value;
|
||||
} else if (parameterName === 'blue') {
|
||||
adjustmentFilter.blue = value;
|
||||
} else if (parameterName === 'alpha') {
|
||||
adjustmentFilter.alpha = value;
|
||||
}
|
||||
}
|
||||
updateStringParameter(filter, parameterName, value) {}
|
||||
updateBooleanParameter(filter, parameterName, value) {}
|
||||
})()
|
||||
);
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {},
|
||||
updateBooleanParameter: function (filter, parameterName, value) {},
|
||||
});
|
||||
}
|
||||
|
@@ -1,30 +1,27 @@
|
||||
namespace gdjs {
|
||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||
'AdvancedBloom',
|
||||
new (class extends gdjs.PixiFiltersTools.PixiFilterCreator {
|
||||
makePIXIFilter(target, effectData) {
|
||||
const advancedBloomFilter = new PIXI.filters.AdvancedBloomFilter();
|
||||
return advancedBloomFilter;
|
||||
gdjs.PixiFiltersTools.registerFilterCreator('AdvancedBloom', {
|
||||
makePIXIFilter: function (target, effectData) {
|
||||
const advancedBloomFilter = new PIXI.filters.AdvancedBloomFilter();
|
||||
return advancedBloomFilter;
|
||||
},
|
||||
updatePreRender: function (filter, target) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const advancedBloomFilter = (filter as unknown) as PIXI.filters.AdvancedBloomFilter;
|
||||
if (parameterName === 'threshold') {
|
||||
advancedBloomFilter.threshold = value;
|
||||
} else if (parameterName === 'bloomScale') {
|
||||
advancedBloomFilter.bloomScale = value;
|
||||
} else if (parameterName === 'brightness') {
|
||||
advancedBloomFilter.brightness = value;
|
||||
} else if (parameterName === 'blur') {
|
||||
advancedBloomFilter.blur = value;
|
||||
} else if (parameterName === 'quality') {
|
||||
advancedBloomFilter.quality = value;
|
||||
} else if (parameterName === 'padding') {
|
||||
advancedBloomFilter.padding = value;
|
||||
}
|
||||
updatePreRender(filter, target) {}
|
||||
updateDoubleParameter(filter, parameterName, value) {
|
||||
const advancedBloomFilter = (filter as unknown) as PIXI.filters.AdvancedBloomFilter;
|
||||
if (parameterName === 'threshold') {
|
||||
advancedBloomFilter.threshold = value;
|
||||
} else if (parameterName === 'bloomScale') {
|
||||
advancedBloomFilter.bloomScale = value;
|
||||
} else if (parameterName === 'brightness') {
|
||||
advancedBloomFilter.brightness = value;
|
||||
} else if (parameterName === 'blur') {
|
||||
advancedBloomFilter.blur = value;
|
||||
} else if (parameterName === 'quality') {
|
||||
advancedBloomFilter.quality = value;
|
||||
} else if (parameterName === 'padding') {
|
||||
advancedBloomFilter.padding = value;
|
||||
}
|
||||
}
|
||||
updateStringParameter(filter, parameterName, value) {}
|
||||
updateBooleanParameter(filter, parameterName, value) {}
|
||||
})()
|
||||
);
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {},
|
||||
updateBooleanParameter: function (filter, parameterName, value) {},
|
||||
});
|
||||
}
|
||||
|
@@ -1,20 +1,17 @@
|
||||
namespace gdjs {
|
||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||
'Ascii',
|
||||
new (class extends gdjs.PixiFiltersTools.PixiFilterCreator {
|
||||
makePIXIFilter(target, effectData) {
|
||||
const asciiFilter = new PIXI.filters.AsciiFilter();
|
||||
return asciiFilter;
|
||||
gdjs.PixiFiltersTools.registerFilterCreator('Ascii', {
|
||||
makePIXIFilter: function (target, effectData) {
|
||||
const asciiFilter = new PIXI.filters.AsciiFilter();
|
||||
return asciiFilter;
|
||||
},
|
||||
updatePreRender: function (filter, target) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const asciiFilter = (filter as unknown) as PIXI.filters.AsciiFilter;
|
||||
if (parameterName === 'size') {
|
||||
asciiFilter.size = value;
|
||||
}
|
||||
updatePreRender(filter, target) {}
|
||||
updateDoubleParameter(filter, parameterName, value) {
|
||||
const asciiFilter = (filter as unknown) as PIXI.filters.AsciiFilter;
|
||||
if (parameterName === 'size') {
|
||||
asciiFilter.size = value;
|
||||
}
|
||||
}
|
||||
updateStringParameter(filter, parameterName, value) {}
|
||||
updateBooleanParameter(filter, parameterName, value) {}
|
||||
})()
|
||||
);
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {},
|
||||
updateBooleanParameter: function (filter, parameterName, value) {},
|
||||
});
|
||||
}
|
||||
|
@@ -1,41 +1,38 @@
|
||||
namespace gdjs {
|
||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||
'Bevel',
|
||||
new (class extends gdjs.PixiFiltersTools.PixiFilterCreator {
|
||||
makePIXIFilter(target, effectData) {
|
||||
const bevelFilter = new PIXI.filters.BevelFilter();
|
||||
return bevelFilter;
|
||||
gdjs.PixiFiltersTools.registerFilterCreator('Bevel', {
|
||||
makePIXIFilter: function (target, effectData) {
|
||||
const bevelFilter = new PIXI.filters.BevelFilter();
|
||||
return bevelFilter;
|
||||
},
|
||||
updatePreRender: function (filter, target) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter;
|
||||
if (parameterName === 'rotation') {
|
||||
bevelFilter.rotation = value;
|
||||
} else if (parameterName === 'thickness') {
|
||||
bevelFilter.thickness = value;
|
||||
} else if (parameterName === 'distance') {
|
||||
// @ts-ignore
|
||||
bevelFilter.distance = value;
|
||||
} else if (parameterName === 'lightAlpha') {
|
||||
bevelFilter.lightAlpha = value;
|
||||
} else if (parameterName === 'shadowAlpha') {
|
||||
bevelFilter.shadowAlpha = value;
|
||||
}
|
||||
updatePreRender(filter, target) {}
|
||||
updateDoubleParameter(filter, parameterName, value) {
|
||||
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter;
|
||||
if (parameterName === 'rotation') {
|
||||
bevelFilter.rotation = value;
|
||||
} else if (parameterName === 'thickness') {
|
||||
bevelFilter.thickness = value;
|
||||
} else if (parameterName === 'distance') {
|
||||
// @ts-ignore
|
||||
bevelFilter.distance = value;
|
||||
} else if (parameterName === 'lightAlpha') {
|
||||
bevelFilter.lightAlpha = value;
|
||||
} else if (parameterName === 'shadowAlpha') {
|
||||
bevelFilter.shadowAlpha = value;
|
||||
}
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {
|
||||
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter;
|
||||
if (parameterName === 'lightColor') {
|
||||
bevelFilter.lightColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
|
||||
value
|
||||
);
|
||||
}
|
||||
updateStringParameter(filter, parameterName, value) {
|
||||
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter;
|
||||
if (parameterName === 'lightColor') {
|
||||
bevelFilter.lightColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
|
||||
value
|
||||
);
|
||||
}
|
||||
if (parameterName === 'shadowColor') {
|
||||
bevelFilter.shadowColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
|
||||
value
|
||||
);
|
||||
}
|
||||
if (parameterName === 'shadowColor') {
|
||||
bevelFilter.shadowColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
|
||||
value
|
||||
);
|
||||
}
|
||||
updateBooleanParameter(filter, parameterName, value) {}
|
||||
})()
|
||||
);
|
||||
},
|
||||
updateBooleanParameter: function (filter, parameterName, value) {},
|
||||
});
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user